PageSourceSearch

https://baunetzwerk.biz/themes/contrib/svg_base_theme_v1/js/script.js?tlnqcb

js baunetzwerk.biz collected 2026-09-25 06:18:48 UTC 22,694 bytes, 649 lines download raw bytes

1/* eslint-disable func-names, no-mutable-exports, comma-dangle, strict */
2
3(($,Drupal, drupalSettings, once) => {
4  Drupal.behaviors.svg_theme_v1 = {
5    attach: function attach(context, settings) {
6      // runs as last
7      once('svg_theme_v1', 'body', context).forEach(() => {
8
9        const desktopContainerClass = '.source--container--main';
10        const mobileContainerClass = '.mobile--mirror--container';
11        if ($(mobileContainerClass).is(':visible')) {
12          // at modal, within header, fix the is sticky class
13          $('header .mobile__toggle').removeClass('sticky--header').addClass('header--is--sticky');
14        } else {
15          setTimeout(() => {
16            window.dispatchEvent(new Event('container_ready'));
17          }, 100);
18        }
19
20        if ($(mobileContainerClass).is(':visible')) {
21          // setTimout necessary here due post rendering latency /remove for better handling embed
22          //setTimeout(copyMainToMobileContainer, 100, desktopContainerClass);
23          copyMainToMobileContainer(desktopContainerClass);
24        }
25
26        // custom JS Event reacting to Adition Library File (imagesrv.adition.com/js/srp.js) loaded.
27        window.addEventListener(
28          'adition_na',
29          (e) => {
30            $('.source--container--main .tile__wrapper.ad_adition').remove();
31            $('.source--container--main .ad__aside').remove();
32            $('.source--container--main .ad__external__bar').remove();
33            $('.source--container--main .ad-entity-container.not-initialized').closest('.fireplace__center').remove();
34          },
35          false,
36        );
37
38        // add general scroll event handler
39        const stickyHeader = document.querySelectorAll('.sticky--header');
40        const minScroll = document.querySelector('.header__inner').getBoundingClientRect().height;
41
42        window.addEventListener('scroll', scrollThrottle(() => {
43          toggleStickyHeaderClass(stickyHeader, minScroll);
44          document.querySelector('.scrollbar-indicator .scrollbar').style.width = scrollPercent() + '%';
45        }, 40));
46
47        (function (e = {}) {
48          postRenderAdjustments();
49        }) ();
50
51        $(window).on('container_ready', () => {
52          // Switching from data-src -> src after final Markup ready. See responsive-embed.html.twig
53          $('iframe').each((eachKey, tmpIframe) => {
54            $(tmpIframe).attr('src', $(tmpIframe).attr('data-src'));
55            $(tmpIframe).removeAttr('data-src');
56          });
57
58          // basic animation init:
59          activateCarousel({});
60          addToggleClass();
61          checkboxIntermediate();
62          initToastNotification();
63          nlBlockHandler();
64          //setImageSource();
65          initSlickSlider();
66          initStickySidebar('.aside__wrapper.make--aside--sticky');
67          // initScrollProgress();
68
69          const hasTocSettings = typeof drupalSettings.toc !== undefined && !!drupalSettings.toc;
70          const hasTocField = $('.toc__content').length > 0;
71          if (hasTocSettings && hasTocField) {
72            toc_init(drupalSettings.toc?.tocAreas, drupalSettings.toc?.headingsSelector);
73          }
74
75          // Call restrictAndInitialize once
76          if (typeof Drupal.ad_entity?.restrictAndInitialize !== undefined) {
77            Drupal.ad_entity?.restrictAndInitialize(Drupal.ad_entity.adContainers, context, settings);
78          }
79
80          // On Mobile, evoke update Maps
81          Drupal.attachBehaviors();
82        });
83      });
84    }
85  };
86
87  Drupal.behaviors.initializeAdContainers = {
88    attach: function (context, settings) {
89      once('initializeAdContainers', '.ad-entity-container', context).forEach(() => {
90        if (!Drupal.ad_entity) return;
91
92        Object.keys(Drupal.ad_entity.adContainers).forEach(key => {
93          let container = Drupal.ad_entity.adContainers[key];
94
95          // Remove 'initialization-disabled' from __ad_entity_metadata.class
96          if (container.__ad_entity_metadata.class.includes('initialization-disabled')) {
97            container.__ad_entity_metadata.class = container.__ad_entity_metadata.class.replace('initialization-disabled', '').trim();
98            // Further cleanup to ensure no extra spaces
99            container.__ad_entity_metadata.class = container.__ad_entity_metadata.class.split(' ').filter(c => c).join(' ');
100          }
101
102          // Assuming 'el' is a DOM element and you want to remove a class from it
103          if (container.el && container.el.classList && container.el.classList.contains('initialization-disabled')) {
104            container.el.classList.remove('initialization-disabled');
105          }
106          $('.ad-entity-container').removeClass('initialization-disabled');
107        });
108      });
109    }
110  };
111
112  Drupal.behaviors.svg_theme_v1_infobox = {
113    attach: function (context) {
114      once('svg_theme_v1_infobox', '.paragraph--type--content-station-infobox .img__panel__wrapper', context).forEach(function (element) {
115
116        var $element = $(element);
117
118        if ($element.find('.img__portrait').length > 0) {
119          $element.addClass('img--portrait');
120        } else {
121          $element.addClass('img--landscape');
122        }
123      });
124    }
125  };
126
127
128  Drupal.behaviors.svg_theme_v1_image = {
129    attach: function attach(context) {
130      // runs as last
131      once('svg_theme_v1_image', 'img', context).forEach(() => {
132        $(window).on('container_ready', () => {
133          setImageSource();
134        });
135      });
136    }
137  }
138
139  // the following runs pre behaviours
140  function toc_init(areaSelector = [], headingsSelector= []) {
141    areaSelector.forEach(function (tocAreaName, areaIndex) {
142
143      const toggleTocContent = function (tocEl) {
144        tocEl.toggle({
145          duration: 100,
146          easing: 'linear',
147          start: () => {
148            $(tocEl).find('dl').hide();
149          },
150          complete: () => {
151            $(tocEl).find('dl').show();
152          }
153        });
154      };
155
156      const tocArea = document.querySelector(tocAreaName);
157      if (!tocArea || typeof tocArea === undefined) {
158        return;
159      }
160      $(tocArea).find('.toc--toggle').on('click', (e) => {
161        e.stopPropagation();
162        toggleTocContent($(e.target).closest('.toc__inner').find('.toc__content'));
163      });
164
165      const tocWrapper = tocArea.querySelector('.toc__content dl');
166      const headingsDefinition = headingsSelector.map((tmpDef) => {
167        return tmpDef.trim() + ':not(.toc--exclude)';
168      }).join(',');
169
170      const headings = [].slice.call(tocArea.querySelectorAll(headingsDefinition));
171      const tocLinkIcon = document.createElement('i');
172      tocLinkIcon.setAttribute('class', 'fi icon-caret-right-fill');
173
174      headings.forEach( (heading, index) => {
175        const tocLinkId = areaIndex + '_toc_' + index;
176        const tocAnchor = document.createElement('a');
177        tocAnchor.setAttribute('title', heading.textContent);
178        tocAnchor.setAttribute('class', 'toc__anchor no--margin');
179        tocAnchor.setAttribute('id', tocLinkId);
180        heading.appendChild(tocAnchor);
181        heading.parentNode.insertBefore(tocAnchor, heading);
182
183        const tocLink = document.createElement(heading.tagName.toLowerCase() == 'h2' ? 'dt' : 'dd');
184        tocLink.setAttribute('title', heading.textContent);
185        tocLink.setAttribute('data-link', '#' + tocLinkId);
186        tocLink.setAttribute('class', 'toc__link toc__link__' + heading.tagName.toLowerCase());
187
188        const tocLinkContent = document.createElement('span');
189        tocLinkContent.textContent = heading.textContent;
190
191        const tocLinkContentFragment = document.createDocumentFragment();
192        tocLinkContentFragment.appendChild(tocLinkIcon.cloneNode(true));
193        tocLinkContentFragment.appendChild(tocLinkContent);
194
195        tocLink.appendChild(tocLinkContentFragment);
196        tocWrapper.appendChild(tocLink);
197      });
198
199      $(tocArea).find('.toc__link').on('click', (e) => {
200        const offsetReference = $(tocArea).find($(e.target).parent().data('link'));
201        const newScrollOffset = parseInt($(offsetReference).offset().top) - 90;
202        $(window).scrollTop(newScrollOffset);
203        toggleTocContent($('.toc__content'));
204      });
205    });
206  }
207
208  function scrollPercent() {
209    return ((window.scrollY) / (document.body.scrollHeight - window.innerHeight) * 100 );
210  }
211
212  function nlBlockHandler() {
213    if ($('.nl__switch').length > 0) {
214      let nlCollapse = new bootstrap.Collapse(document.getElementById('NLcollapse'), {
215        toggle: false
216      });
217
218      $('.nl__switch').on('click', (ev) => {
219
220        const nlBlockWrapper = $(ev.currentTarget).closest('.nl__block__wrapper');
221        let nlOptInForm = nlBlockWrapper.find('.nl__opt__in__form');
222        if ($(ev.currentTarget).data('state') === 'add') {
223          $(ev.currentTarget).data('state', 'remove');
224          $(ev.currentTarget).find('.nl--add').addClass('d-none');
225          $(ev.currentTarget).find('.nl--remove').removeClass('d-none');
226        } else {
227          $(ev.currentTarget).data('state', 'add');
228          $(ev.currentTarget).find('.nl--remove').addClass('d-none');
229          $(ev.currentTarget).find('.nl--add').removeClass('d-none');
230        }
231
232        const inxmailInputName = 'input#' + $(ev.currentTarget).data('newsletter') + '[name="INXMAIL_SUBSCRIPTION"]';
233        if (nlOptInForm.find(inxmailInputName).length > 0) {
234          // remove -> has been added and Current State = Added
235          const nextState = $(ev.currentTarget).data('state') === 'remove';
236          nlOptInForm.find('input#' + $(ev.currentTarget).data('newsletter') + '[name="INXMAIL_SUBSCRIPTION"]').prop("checked", nextState);
237        }
238
239        let nlCount = 0;
240        nlBlockWrapper.find('.tile__content .nl__switch').each((elIndex, tmpEl) => {
241          nlCount += $(tmpEl).data('state') === 'remove' ? 1 : 0;
242        });
243
244        nlOptInForm.find('.nl__counter').text(nlCount);
245        nlCollapse.show();
246
247        ev.stopPropagation();
248        ev.preventDefault();
249      });
250    }
251  }
252
253  function copyMainToMobileContainer(desktopContainerClass) {
254    const sourceMain = '.source--container--main';
255    const destMain = '.mobile--mirror--container';
256    const destHasChildren = $(destMain).children().length > 0;
257
258    if (!destHasChildren && $(sourceMain).length > 0) {
259      let elColNr = 0;
260      $($(sourceMain).children()).each((groupIndex, groupEl) => {
261        const copyEls = $(groupEl).children().first().children().clone();
262        copyEls.each((index, el) => {
263          if (!el.classList.value.includes("order-")) {
264            el.classList.add("order-" + (elColNr + 1));
265            el.classList.add("order-md-0");
266          }
267          ensureCarouselMobileId(el);
268          ensurePhotoswipeMobileId(el);
269          $(el).appendTo(destMain);
270          elColNr++;
271        });
272      });
273      $(desktopContainerClass).remove();
274    }
275    setTimeout(() => {
276      window.dispatchEvent(new Event('container_ready'));
277    }, 100);
278  }
279
280  function postRenderAdjustments() {
281    if ($(".countup").length > 0) {
282      $(".countup").each((counterIndex, counter) => {
283        startCountUp(
284          $(counter).find(".countup__number").attr("id"),
285          $(counter).find(".countup__number").data('nr')
286        );
287      });
288    }
289
290
291    $(window).on('container_ready', () => {
292      if ($(".pswp-gallery").length > 0) {
293        $(".pswp-gallery").each((pswpGalleryIndex, pswpGallery) => {
294          initPhotoswipe(pswpGallery);
295        });
296      }
297    });
298
299
300    if ($(".cancel__search").length > 0) {
301      $(".cancel__search").on("click", (e) => {
302        $(e.currentTarget).parent().find(":input").val("");
303      });
304    }
305
306    if (
307      $(".sticky--header").length > 0 &&
308      !$(".sticky--header").hasClass('header__is__sticky')
309      //!$(".sticky--header").hasClass("is--sticky")
310    ) {
311      // toggleStickyTopClass(document.querySelector(".sticky--header"));
312      // toggleStickyHeaderClass();
313    }
314
315    /*
316    if ($(".scroll__up").length) {
317      // footer should be available and scroll top functional
318      // toggleStickyTopClass(document.querySelector(".scroll__up"));
319      toggleStickyHeaderClass(document.querySelector(".scroll__up"));
320    }
321    */
322
323    if ($("#searchModal").length > 0) {
324      // set focus on input box
325      document
326        .getElementById("searchModal")
327        .addEventListener("shown.bs.modal", (event) => {
328          document.querySelector(".search__input").focus();
329        });
330    }
331  }
332
333  function addToggleClass() {
334    $(".js--toggle").on("click", (el) => {
335      const targetEl = document.querySelector(el.currentTarget.dataset.exptarget);
336      targetEl.classList.toggle(el.currentTarget.dataset.expclass);
337    });
338  }
339
340  function checkboxIntermediate() {
341    if ($(".form-check-input.intermediate").length > 0) {
342      document.querySelector(
343        ".form-check-input.intermediate"
344      ).indeterminate = true;
345    }
346  }
347
348  function initSlickSlider() {
349    // Slick slider for both: slide (for) + nav
350    const sliderForNavWrapper = '.slider__for__nav';
351    const prevArrow = '<button type="button" class="slick-prev rounded--icon"><i class="fi icon-arrow-left-short" aria-label="previous" title="prev" role="link"></i></button>';
352    const nextArrow = '<button type="button" class="slick-next rounded--icon"><i class="fi icon-arrow-right-short" aria-label="next" title="next" role="link"></i></button>';
353    if ($(sliderForNavWrapper).length > 0) {
354      $(sliderForNavWrapper).each((sliderIndex, sliderEl) => {
355        const sliderFor = $(sliderEl).find('.slider-for');
356        const sliderNav = $(sliderEl).find('.slider-nav');
357
358        let sliderWidth = $(sliderEl).closest(sliderForNavWrapper).parent().width();
359        if (sliderWidth > 0) {
360          $(sliderForNavWrapper).css('width', sliderWidth);
361        }
362
363        $(sliderFor).on('init', function(event, slick){
364          $(this).append('<div class="slider__count"><span class="current">1</span>/<span id="total">
364'+slick.slideCount+'</span></div>');
365          $(this).append('<div class="slider__fullscreen d-none d-md-block"><span><i class="fi icon-zoom-in" role="button"></i></span></div>');
366        });
367
368        /*
369        $(sliderFor).on('setPosition', (event, slick) => {
370          console.info('setPosition', sliderWidth);
371          sliderWidth = $(sliderEl).closest(sliderForNavWrapper).parent().width();
372          $(sliderForNavWrapper).css('max-width', sliderWidth);
373          slick.slickSetOption('refresh', true);
374        });
375        */
376
377        $(sliderFor).slick({
378          slidesToShow: 1,
379          slidesToScroll: 1,
380          arrows: true,
381          fade: true,
382          asNavFor: sliderNav,
383          nextArrow: nextArrow,
384          prevArrow: prevArrow
385        });
386
387        $(sliderNav).slick({
388          slidesToShow: 2,
389          slidesToScroll: 1,
390          asNavFor: sliderFor,
391          dots: false,
392          infinite: true,
393          centerMode: true,
394          focusOnSelect: true,
395          nextArrow: nextArrow,
396          prevArrow: prevArrow,
397        });
398
399        $(sliderFor)
400          .on('afterChange', function(event, slick, currentSlide, nextSlide){
401            $(this).find('.slider__count .current').html(currentSlide + 1);
402          });
403      });
404    }
405
406    // Slick Slider for only nav part
407    const sliderNavWrapper = 'ul.slider-nav';
408    if ($(sliderNavWrapper).length > 0) {
409      $(sliderNavWrapper).each((sliderIndex, sliderNavEl) => {
410        $(sliderNavEl).slick({
411          variableWidth: true,
412          dots: false,
413          infinite: false,
414          easing: 'swing',
415          centerMode: false,
416          focusOnSelect: false,
417          slidesToShow: 3,
418          slidesToScroll: 3,
419          nextArrow: '<button type="button" class="slick-next rounded--icon"><i class="fi full icon-chevron-right" aria-label="next" title="next" role="link"></i></button>',
420          prevArrow: '<button type="button" class="slick-prev rounded--icon"><i class="fi full icon-chevron-left" aria-label="previous" title="prev" role="link"></i></button>',
421          responsive: [
422            {
423              breakpoint: 600,
424              settings: {
425                slidesToShow: 3,
426                slidesToScroll: 3,
427              }
428            }
429          ]
430        });
431      });
432    }
433  }
434
435  function initStickySidebar(slideEl) {
436    if(typeof $(slideEl) == undefined) return;
437
438    $(slideEl).stickySidebar({
439      topSpacing: 60,
440      bottomSpacing: 20
441    });
442  }
443
444  function startCountUp(targetId, countNumber) {
445    if ($(targetId).length > 0) {
446      const counterOptions = {
447        startVal: 0,
448        decimalPlaces: 0,
449        duration: 2,
450        separator: ".",
451        decimal: ",",
452        enableScrollSpy: true,
453        scrollSpyDelay: 200,
454        scrollSpyOnce: true,
455      };
456      const countUpCounter = new countUp.CountUp(
457        targetId,
458        countNumber,
459        counterOptions
460      );
461      if (!countUpCounter.error) {
462        countUpCounter.start();
463      } /* else {
464      console.error(countUpCounter.error);
465    } */
466    }
467
468  }
469
470
471  const scrollThrottle = (fn, delay) => {
472    let time = Date.now();
473    return () => {
474      if((time + delay - Date.now()) <= 0) {
475        fn();
476        time = Date.now();
477      }
478    }
479  }
480
481  function toggleStickyHeaderClass(stickyHeader, minScroll) {
482    const stickyHeaderClass = 'header--is--sticky';
483    if (window.scrollY > minScroll) {
484      stickyHeader.forEach((stickyWatchEl) => {
485        stickyWatchEl.classList.add(stickyHeaderClass);
486      });
487    } else {
488      stickyHeader.forEach((stickyWatchEl) => {
489        stickyWatchEl.classList.remove(stickyHeaderClass);
490      });
491    }
492  }
493
494  /*
495  function toggleStickyTopClass(el) {
496    const switchThreshold =
497      window.scrollY + el.getBoundingClientRect().top + 10;
498
499    const onScrollDebounced = debounce((event) => {
500      if (window.scrollY < switchThreshold) {
501        el.classList.remove("is--sticky");
502      } else {
503        el.classList.add("is--sticky");
504      }
505    }, 7);
506
507    window.addEventListener("scroll", onScrollDebounced, el);
508
509    function debounce(func, wait) {
510      let timeout;
511      return function () {
512        if (timeout) {
513          clearTimeout(timeout);
514        }
515        timeout = setTimeout(() => {
516          func.apply(this, arguments);
517        }, wait);
518      };
519    }
520  }*/
521
522// we copy from source--container--main -> mobile--mirror--container and due to this, the JS Elements has to be
523// initialised within the new container. The following function helps to extend the ID in order that BS.Carousel
524// creates a different (separate) instance and functionality
525  function ensureCarouselMobileId(el) {
526    if ($(el).hasClass('carousel')) {
527      el.id += "Mobile";
528      Array.from(el.children).forEach((carouselEl, carElIndex) => {
529        if (carouselEl.classList.contains("carousel-indicators")) {
530          for (let i = 0; i < el.children[0].children.length; i++) {
531            el.children[carElIndex].children[i].dataset.bsTarget = "#" + el.id;
532          }
533        } else if (carouselEl.classList.contains("carousel-control-prev")) {
534          el.children[carElIndex].dataset.bsTarget = "#" + el.id;
535        } else if (carouselEl.classList.contains("carousel-control-next")) {
536          el.children[carElIndex].dataset.bsTarget = "#" + el.id;
537        }
538      });
539    }
540  }
541
542  function ensurePhotoswipeMobileId(el) {
543    $(el).find('.pswp-gallery').each(function () {
544      this.id += "_mobile";
545    });
546  }
547
548  // The Carousel should be init while swipe and therefor the .to(0) has to be applied. Also on Mobile the crossfade
549  // effect is more convenient.
550  function activateCarousel({ photoswipe = true }) {
551    $(".carousel").each((carIndex, carouselEl) => {
552      // Carousel focus
553      let tmpCarousel = bootstrap.Carousel.getOrCreateInstance($(carouselEl)[0]);
554      tmpCarousel.to(0);
555
556      // make Gallery Images clickable
557      const carouselGallery = $(carouselEl).find(
558        ".carousel__gallery__thumbnails"
559      );
560      if (carouselGallery.length > 0) {
561        $(carouselGallery)
562          .find(".carousel__image__thumbnail")
563          .on("click", function () {
564            tmpCarousel.to($(this).data("slide-to"));
565          });
566      }
567    });
568  }
569
570  function initPhotoswipe(gallery) {
571    const photoswipeGallery = new PhotoSwipeLightbox({
572      gallery: "#" + gallery.id,
573      children: 'a',
574      pswpModule: PhotoSwipe,
575    });
576
577    photoswipeGallery.init();
578  }
579
580  function initToastNotification() {
581    $(window).on('container_ready', () => {
582      const toastElList = document.querySelectorAll(".toast");
583      [...toastElList].map((toastEl) => {
584        let tmpToast = new bootstrap.Toast(toastEl);
585        tmpToast.show();
586      });
587    });
588  }
589
590  function setImageSource() {
591    const imgLoaded = (imgObj) => {
592      imgObj.classList.add('img--loaded');
593      const parentEl = imgObj.closest('.img__wrapper');
594      const parentWidth = getParentWidth(parentEl);
595      const imgSrc = getImgSize(imgObj, parentWidth);
596      if (imgSrc) {
597        imgObj.setAttribute('src', imgSrc);
598      }
599      observer.unobserve(imgObj);
600    }
601
602    const getImgSize = (imgObj, parentWidth) => {
603      for ( let dataSize in imgObj.dataset) {
604        if (dataSize > parentWidth) {
605          return imgObj.dataset[dataSize];
606        }
607      }
608      return false;
609    }
610
611    const getParentWidth = (parentEl) => {
612      const parentElStyles = window.getComputedStyle(parentEl);
613      const parentElPaddingLeft = parseFloat(parentElStyles.paddingLeft);
614      const parentElPaddingRight = parseFloat(parentElStyles.paddingRight);
615      return parentEl.clientWidth - parentElPaddingLeft - parentElPaddingRight;
616    }
617
618    // https://redstapler.co/how-to-check-if-all-images-are-loaded-with-javascript/
619    const observer = new IntersectionObserver(function(entries) {
620      entries.forEach((entry) => {
621        if (entry.isIntersecting && $(entry.target).closest('.ad-entity-adition').length === 0) {
622          entry.target.addEventListener('load', function() {
623            // imgLoaded(entry.target);
624          });
625          if (entry.target.complete) {
626            // console.info('complete');
627            imgLoaded(entry.target);
628          }
629          // rem object from tracking
630          observer.unobserve(entry.target);
631        }
632      });
633    });
634
635    let imgSelector = '.img__wrapper img';
636    let imgElements = document.querySelectorAll(imgSelector);
637    imgElements.forEach(function(imgElement) {
638      observer.observe(imgElement);
639    });
640  }
641}) (jQuery, Drupal, drupalSettings, once);
642
643
644function DrupalGeolocationGoogleLoader() {
645  Drupal.geolocation.maps.mapProviderCallback('Google');
646}
647
648
649

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.