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.