1//------------------------------------- 2// FUNCTIONS 3//------------------------------------- 4//-- Calculate Navigation Width 5const calculate_nav_width = () => { 6 // Ensure DOM elements exist before calculating 7 if (!d.q('.homelink') || !d.q('nav')) { 8 // Elements not ready yet 9 return 10 } 11 12 // Update homelink width 13 const homelinkEl = d.q('.homelink') 14 15 // Check if homelink is properly styled (should not be block-level spanning full width) 16 const homelinkDisplay = window.getComputedStyle(homelinkEl).display 17 const homelinkFloat = window.getComputedStyle(homelinkEl).float 18 const homelinkPosition = window.getComputedStyle(homelinkEl).position 19 20 // If homelink is display:block and not floated/positioned, it's not ready yet 21 if (homelinkDisplay === 'block' && homelinkFloat === 'none' && homelinkPosition === 'static') { 22 nav_width = 0 23 return 24 } 25 26 homelink_width = homelinkEl.scrollWidth 27 28 // Additional safety check - if homelink is taking full window width, something's wrong 29 if (homelink_width >= window.innerWidth - 10) { 30 nav_width = 0 31 return 32 } 33 34 if (nav_horizontal_right_left) { 35 let nav_padding_side = 36 parseInt(getComputedStyle(d.q('nav')).paddingLeft) + parseInt(getComputedStyle(d.q('nav')).paddingRight) 37 38 let btn_margin = 0 39 let btn_border = 0 40 let number_of_btns = 0 41 nav_btns_width = 0 42 43 if (d.q('nav .buttons-wrap-header .btn')) { 44 number_of_btns = d.qAll('nav .buttons-wrap-header .btn').length 45 btn_margin = parseInt(getComputedStyle(d.q('nav .buttons-wrap-header .btn')).marginRight) || 0 46 btn_border = parseInt(window.getComputedStyle(d.q('nav .buttons-wrap-header .btn'), null).borderLeftWidth) * 2 || 0 47 for (let n = 0; n < number_of_btns; n++) { 48 nav_btns_width = nav_btns_width + d.qAll('nav .buttons-wrap-header .btn')[n].scrollWidth 49 } 50 } 51 52 nav_btns_width = nav_btns_width + btn_border * 2 * number_of_btns + btn_margin * number_of_btns 53 nav_dropdown_lang_width = 0 54 55 if (template != 15 && d.q('.drodown-wrap--lang')) { 56 nav_dropdown_lang_width = d.q('.drodown-wrap--lang').scrollWidth || 0 57 } 58 59 let nav_items_width = 0 60 if (document.getElementsByClassName('nav__items')[0]) { 61 let navElement = document.getElementsByClassName('nav__items')[0] 62 nav_items_width = navElement.scrollWidth || 0 63 } 64 65 nav_width = 66 homelink_width + 67 nav_items_width + 68 nav_btns_width + 69 nav_dropdown_lang_width + 70 nav_padding_side + 71 20 72 } 73} 74 75//-- Adjust navigation widths when content overflows 76const adjust_nav_widths = () => { 77 let window_width = window.innerWidth 78 79 if (nav_horizontal_left) { 80 if (nav_width >= window_width) { 81 d.q('.nav .nav-items-wrap').style.width = 'calc(100% - ' + d.q('.nav .nav__buttons').scrollWidth + 'px)' 82 d.q('.nav .homelink').style.width = '100%' 83 } else { 84 d.q('.nav .nav-items-wrap').style.width = 'auto' 85 d.q('.nav .homelink').style.width = 'auto' 86 } 87 } 88 89 if (nav_horizontal_right) { 90 if (nav_width >= window_width) { 91 d.q('.nav .homelink').style.width = 'calc(100% - ' + d.q('.nav .nav__buttons').scrollWidth + 'px)' 92 } else { 93 d.q('.nav .homelink').style.width = 'auto' 94 } 95 } 96 97 if (nav_horizontal_center) { 98 let nav_height = d.q('nav').offsetHeight 99 if (nav_height >= nav_height_max) { 100 d.q('.nav--buttons-only .homelink').style.width = 101 'calc(100% - ' + 102 d.q('.nav--buttons-only .nav__buttons').scrollWidth + 103 'px - ' + 104 d.q('.nav--buttons-only .buttons-wrap-header').scrollWidth + 105 'px - 24px)' 106 } else { 107 d.q('.nav--buttons-only .homelink').style.width = 'auto' 108 } 109 } 110} 111 112//-- Display Burger icon 113const display_burger_icon = () => { 114 let window_width = window.innerWidth 115 116 if (nav_horizontal_right_left) { 117 // Determine if burger menu should show based on window width first 118 let should_show_burger = false 119 120 // Fixed mobile breakpoint 121 if (window_width <= 768) { 122 // Mobile - always show burger 123 should_show_burger = true 124 } else if (window_width <= 1024) { 125 // Tablet range - calculate to see if nav fits 126 // Temporarily show nav items to get accurate measurement 127 let navItems = d.q('.nav__items') 128 let langDropdown = d.q('.drodown-wrap--lang') 129 let wasHidden = false 130 131 if (navItems && navItems.style.display === 'none') { 132 navItems.style.display = 'flex' 133 wasHidden = true 134 } 135 if (langDropdown && langDropdown.style.display === 'none') { 136 langDropdown.style.display = 'flex' 137 } 138 139 // Calculate with items visible 140 calculate_nav_width() 141 142 // Hide again if calculation shows we need burger 143 if (nav_width === 0) { 144 // Measurement failed, if nav was hidden before, keep it hidden 145 should_show_burger = wasHidden 146 } else if (wasHidden || nav_width + 50 > window_width) { 147 should_show_burger = true 148 } 149 } else { 150 // Desktop (> 1024px) - only show burger if content really doesn't fit 151 // Temporarily show nav items to measure 152 let navItems = d.q('.nav__items') 153 let langDropdown = d.q('.drodown-wrap--lang') 154 155 if (navItems && navItems.style.display === 'none') { 156 navItems.style.display = 'flex' 157 } 158 if (langDropdown && langDropdown.style.display === 'none') { 159 langDropdown.style.display = 'flex' 160 } 161 162 // Calculate with items visible 163 calculate_nav_width() 164 165 // For desktop, be more conservative - only show burger if really needed 166 if (nav_width === 0) { 167 // Measurement failed, default to showing full nav on desktop 168 should_show_burger = false 169 } else if (nav_width > window_width - 20) { 170 should_show_burger = true 171 } else { 172 should_show_burger = false 173 } 174 } 175 176 if (should_show_burger) { 177 // Show burger menu 178 if (d.q('.nav__items')) d.q('.nav__items').style.display = 'none' 179 if (d.q('.drodown-wrap--lang')) d.q('.drodown-wrap--lang').style.display = 'none' 180 if (window_width <= 768 && d.q('nav .buttons-wrap-header')) d.q('nav .buttons-wrap-header').style.display = 'none' 181 if (d.q('.burger-button')) d.q('.burger-button').classList.add('show') 182 } else { 183 // Hide burger menu 184 if (d.q('.nav__items')) d.q('.nav__items').style.display = 'flex' 185 if (d.q('.drodown-wrap--lang')) d.q('.drodown-wrap--lang').style.display = 'flex' 186 if (d.q('nav .buttons-wrap-header')) d.q('nav .buttons-wrap-header').style.display = 'flex' 187 if (d.q('.burger-button')) d.q('.burger-button').classList.remove('show') 188 remove_burger_menu() 189 } 190 } 191 192 if (nav_horizontal_center) { 193 let nav_height = d.q('nav').offsetHeight 194 195 if (nav_height >= nav_height_max) { 196 d.q('.nav--buttons-only').style.top = '0' 197 d.q('nav').style.top = '-100%' 198 d.q('.burger-button').classList.add('show') 199 } else { 200 d.q('nav').style.top = '0' 201 d.q('.nav--buttons-only').style.top = '-100%' 202 d.q('.burger-button').classList.remove('show') 203 remove_burger_menu() 204 } 205 } 206 207 //-- If no logo and title too long 208 setTimeout(function () { 209 adjust_nav_widths() 210 }, 100) 211} 212 213//-- Display Burger menu 214const display_burger_menu = () => { 215 if (nav_vertical) { 216 d.q('.nav-vertical').classList.toggle('show') 217 d.q('body').classList.toggle('overlay') 218 } else { 219 d.q('.burger-menu').classList.toggle('show') 220 } 221 d.q('.burger-button').classList.toggle('active')
222 d.q('body').classList.toggle('burger-menu-enable') 223 224 // Update aria-expanded for accessibility 225 const burgerBtn = d.q('.burger-button') 226 if (burgerBtn) { 227 const isExpanded = burgerBtn.classList.contains('active') 228 burgerBtn.setAttribute('aria-expanded', isExpanded ? 'true' : 'false') 229 } 230} 231 232//-- Remove Burger menu 233const remove_burger_menu = () => { 234 if (nav_vertical) { 235 d.q('.nav-vertical').classList.remove('show') 236 d.q('body').classList.remove('overlay') 237 } else { 238 d.q('.burger-menu').classList.remove('show') 239 } 240 d.q('.burger-button').classList.remove('active') 241 d.q('body').classList.remove('burger-menu-enable') 242 243 // Update aria-expanded for accessibility 244 const burgerBtn = d.q('.burger-button') 245 if (burgerBtn) { 246 burgerBtn.setAttribute('aria-expanded', 'false') 247 } 248} 249 250//-- Remove buttons on nav for tiny screen 251const remove_buttons_menu = () => { 252 let window_width = window.innerWidth 253 // Check if buttons should be removed for mobile view 254 255 // Use a fixed breakpoint for consistency 256 if (window_width <= 480) { 257 // Hiding buttons (mobile width exceeded) 258 if (nav_horizontal_right_left) d.q('.buttons-wrap-header').style.display = 'none' 259 if (nav_vertical) d.q('header .buttons-wrap-header').style.display = 'none' 260 if (nav_horizontal_center) 261 for (let n = 0; n < d.qAll('.nav--buttons-only .btn').length; n++) 262 d.qAll('.nav--buttons-only .btn')[n].style.display = 'none' 263 } else { 264 if (nav_horizontal_right_left) { 265 if (window_width <= 768 && d.q('.burger-button') && d.q('.burger-button').classList.contains('show')) { 266 d.q('nav .buttons-wrap-header').style.display = 'none' 267 } else { 268 d.q('nav .buttons-wrap-header').style.display = 'flex' 269 } 270 } 271 if (nav_vertical) d.q('header .buttons-wrap-header').style.display = 'flex' 272 if (nav_horizontal_center) 273 for (let n = 0; n < d.qAll('.nav--buttons-only .btn').length; n++) 274 d.qAll('.nav--buttons-only .btn')[n].style.display = 'flex' 275 } 276} 277 278//-- Dropdown Burger Menu 279const display_burger_dropdown = (param) => { 280 param.offsetParent.classList.toggle('visible') 281 282 // Update aria-expanded for accessibility 283 const isExpanded = param.offsetParent.classList.contains('visible') 284 param.setAttribute('aria-expanded', isExpanded ? 'true' : 'false') 285} 286 287//-- Sticky nav menu 288const sticky_menu_nav = () => { 289 let nav_height = d.q('nav').offsetHeight 290 if (nav_height >= nav_height_max) { 291 let nav_height = d.q('.nav--buttons-only').offsetHeight 292 d.q('.menu-nav').style.top = nav_height + 'px' 293 } else { 294 let nav_height = d.q('.hello').offsetHeight 295 d.q('.menu-nav').style.top = nav_height + 'px' 296 } 297} 298 299//-- Menu active item 300const menu_active_item = () => { 301 for (let n = 0; n < d.qAll('.menu-nav__item').length; n++) { 302 d.qAll('.menu-nav__item')[0].classList.add('active') 303 d.qAll('.menu-nav__item')[n].onclick = function (e) { 304 for (let j = 0; j < d.qAll('.menu-nav__item').length; j++) { 305 d.qAll('.menu-nav__item')[j].classList.remove('active') 306 } 307 this.classList.add('active') 308 } 309 } 310} 311 312//-- Menu active item ⢠Summary 313const menu_active_item_summary = () => { 314 for (let n = 0; n < d.qAll('.menu-nav__item--home').length; n++) { 315 d.qAll('.menu-wrap')[0].classList.add('active') 316 // Calculate height after a small delay to ensure content is rendered 317 setTimeout(() => { 318 if (d.q('.menus-wrapper') && d.qAll('.menu-wrap')[0]) { 319 d.q('.menus-wrapper').style.height = d.qAll('.menu-wrap')[0].offsetHeight + 'px' 320 } 321 }, 100) 322 d.qAll('.menu-nav__item--home')[0].classList.add('active') 323 324 d.qAll('.menu-nav__item--home')[n].onclick = function (e) { 325 for (let j = 0; j < d.qAll('.menu-wrap').length; j++) { 326 d.qAll('.menu-wrap')[j].classList.remove('active') 327 328 if (this.dataset.anchor == d.qAll('.menu-wrap')[j].getAttribute('id')) { 329 d.qAll('.menu-wrap')[j].classList.add('active') 330 d.q('.menus-wrapper').style.height = d.qAll('.menu-wrap')[j].offsetHeight + 'px' 331 } 332 } 333 334 for (let j = 0; j < d.qAll('.menu-nav__item--home').length; j++) { 335 d.qAll('.menu-nav__item--home')[j].classList.remove('active') 336 } 337 338 this.classList.add('active') 339 } 340 } 341} 342 343//-- Contact form with accessible error handling (WCAG 3.3.1, 3.3.3) 344if ($('#contact-form').length > 0) { 345 $('#contact-form').validate({ 346 // Use custom error placement for accessibility 347 errorPlacement: function (error, element) { 348 var errorId = element.attr('id') + '-error' 349 var errorContainer = $('#' + errorId) 350 if (errorContainer.length > 0) { 351 errorContainer.text(error.text()) 352 } 353 },
354 // Add aria-invalid when field is invalid 355 highlight: function (element) { 356 $(element).attr('aria-invalid', 'true') 357 }, 358 // Remove aria-invalid when field is valid 359 unhighlight: function (element) { 360 $(element).attr('aria-invalid', 'false') 361 var errorId = $(element).attr('id') + '-error' 362 $('#' + errorId).text('') 363 }, 364 // Announce errors to screen readers on form submit 365 invalidHandler: function (event, validator) { 366 var errorCount = validator.numberOfInvalids() 367 if (errorCount > 0) { 368 var errorSummary = $('#contact-form-errors') 369 var message = errorCount === 1 370 ? '1 error found. Please correct the highlighted field.' 371 : errorCount + ' errors found. Please correct the highlighted fields.' 372 errorSummary.text(message) 373 // Focus first invalid field 374 $(validator.errorList[0].element).focus() 375 } 376 }, 377 submitHandler: function (form) { 378 // Clear error summary on successful submit 379 $('#contact-form-errors').text('') 380 var options = { 381 target: '#contact-form', // target element(s) to be updated with server response 382 beforeSubmit: function (formData, jqForm, options) { 383 var queryString = $.param(formData) 384 return true 385 }, 386 success: function (data) { 387 $('.step2').toggleClass('hidden') 388 // Send a google analytics event 389 $(window).trigger('contact-form-sent') 390 }, 391 url: '/contact-form.php', 392 } 393 $(form).ajaxSubmit(options) 394 return false 395 }, 396 }) 397} 398 399//-- Fancybox 400$('[data-fancybox].iframe--widget').fancybox({ 401 buttons: [], 402 touch: false, 403 beforeLoad: function () { 404 if (!$('.fancybox-iframe').parent().hasClass('iframe-wrapper')) { 405 $('.fancybox-iframe').wrap('<div class="iframe-wrapper"/>') 406 } 407 }, 408}) 409 410$('[data-fancybox].iframe--contact').fancybox({ 411 buttons: [], 412 touch: false, 413 beforeLoad: function () { 414 if (!$('.fancybox-iframe').parent().hasClass('iframe-wrapper')) { 415 $('.fancybox-iframe').wrap('<div class="iframe-wrapper"/>') 416 } 417 }, 418}) 419 420$('[data-fancybox]:not(.iframe--widget):not(.iframe--menus)').fancybox({ 421 iframe: { 422 css: { 423 height: '450px', 424 }, 425 }, 426 buttons: ['close'], 427 beforeLoad: function () { 428 if (!$('.fancybox-iframe').parent().hasClass('iframe-wrapper')) { 429 $('.fancybox-iframe').wrap('<div class="iframe-wrapper"/>') 430 } 431 }, 432}) 433 434function bindEvent(element, eventName, eventHandler) { 435 if (element.addEventListener) { 436 element.addEventListener(eventName, eventHandler, false) 437 } else if (element.attachEvent) { 438 element.attachEvent('on' + eventName, eventHandler) 439 } 440} 441 442//-- Listen to message from child window 443bindEvent(window, 'message', function (e) { 444 if (e.data === 'close-widget') { 445 $.fancybox.getInstance().close() 446 } 447}) 448 449//-- Slider 450const slider = () => { 451 if ($('.slide').length > 0) { 452 $('.slide.active').cycle({ 453 log: false, 454 prev: '.nav__btn--prev', 455 next: '.nav__btn--next', 456 slides: '>div', 457 }) 458 459 $('.albums li').click(function (e) { 460 if (!$(this).hasClass('active')) { 461 var slider = $(this).children('a').attr('data-slider') 462 $('.albums li.active').removeClass('active') 463 $(this).addClass('active') 464 $('.slide.active').fadeOut(200, function () { 465 $('.slide.active').removeClass('active').cycle('pause') 466 $('#' + slider).fadeIn(200, function () { 467 if ($('#' + slider).is('.cycle-paused')) { 468 $(this).cycle('resume').addClass('active') 469 } else { 470 $('#' + slider) 471 .cycle({ 472 log: false, 473 prev: '.nav__btn--prev', 474 next: '.nav__btn--next', 475 slides: '>div', 476 }) 477 .addClass('active') 478 } 479 }) 480 }) 481 } 482 return false 483 }) 484 } 485} 486 487//------------------------------------- 488// MAIN 489//------------------------------------- 490const main = () => { 491 // Initialize navigation measurements first 492 initialize_nav_measurements() 493 494 // Then check if burger icon should be displayed 495 if (nav_horizontal_right_left || nav_horizontal_center) display_burger_icon() 496 if (nav_horizontal_center && page_name == 'menus') sticky_menu_nav() 497 if (nav_horizontal_right_left || nav_horizontal_center || nav_vertical) remove_buttons_menu() 498 if (nav_vertical) d.q('.nav-items-wrap').style.height = 'calc(100% - ' + d.q('.nav__bottom').scrollHeight + 'px)' 499 menu_active_item() 500 menu_active_item_summary() 501 // if ((template_w_slider && (page_name == 'gallery' || page_name == 'custom')) || template == 0) 502 slider() 503 504 if (nav_vertical) { 505 if (768 >= window.innerWidth) { 506 d.q('.header-vertical .homelink').style.width = 507 'calc(100% - ' + d.q('.header-vertical .nav__buttons').scrollWidth + 'px)' 508 } else { 509 d.q('.header-vertical .homelink').style.width = 'auto' 510 } 511 } else if (nav_inside) { 512 if (768 >= window.innerWidth) { 513 d.q('.nav-inside .homelink').style.width = 514 'calc(100% - ' + d.q('.nav-inside .burger-button').scrollWidth + 'px)' 515 } else { 516 d.q('.nav-inside .homelink').style.width = 'auto' 517 } 518 } 519 520 //-- Delete loader (Must be before any external dependency as a fallback safety) 521 setTimeout(function () { 522 d.q('body').style.overflow = 'initial' 523 d.q('.loader-wrap').classList.add('hide') 524 }, 400) 525 526 //-- Opening hours active day 527 var day = new Date().getDay() || 7 528 $('.day' + day).addClass('day-wrap--active') 529 530 //-- Active page
531 let nav_item_class = d.q('.nav__item--' + page_name) 532 if (page_name != 'home' && nav_item_class) nav_item_class.classList.add('active') 533 534 //-- Smooth scrolling to page anchor on click 535 $("a[href*='#']:not([href='#'])").click(function () { 536 if ( 537 location.hostname == this.hostname && 538 this.pathname.replace(/^\//, '') == location.pathname.replace(/^\//, '') 539 ) { 540 let target = $(this.hash) 541 let window_width = $(window).width() 542 let menu_nav_height = $('.menu-nav').outerHeight() 543 let nav_height = !nav_vertical ? $('nav').outerHeight() : $('header').outerHeight() 544 545 //-- Conditions 546 if (page_name == 'menus') { 547 if ( 548 (window_width <= 970 && (template == 1 || template == 4)) || 549 (window_width <= 750 && (template == 2 || template == 5)) 550 ) { 551 nav_height = nav_height + menu_nav_height 552 } else if ( 553 (window_width <= 1220 && (template == 2 || template == 5)) || 554 (window_width <= 750 && (template == 3 || template == 6)) || 555 (window_width >= 750 && template == 9) 556 ) { 557 nav_height = menu_nav_height 558 } else if ( 559 (window_width >= 1220 && (template == 2 || template == 5)) || 560 (window_width >= 750 && (template == 3 || template == 6)) 561 ) { 562 nav_height = 20 563 } else if (window_width >= 970 && (template == 1 || template == 4)) { 564 nav_height = nav_height 565 } else { 566 nav_height = nav_height + menu_nav_height 567 } 568 } else if (template == 0) { 569 nav_height = menu_nav_height 570 } else if (template == 10) { 571 nav_height = menu_nav_height 572 } else if (page_name == 'gallery') { 573 if (template == 3 || template == 6) { 574 nav_height = 20 575 } else { 576 nav_height = nav_height + 20 577 } 578 } 579 580 target = target.length ? target : $('[name=' + this.hash.slice(1) + ']') 581 if (target.length) { 582 $('html, body').animate( 583 { 584 scrollTop: target.offset().top - nav_height, 585 }, 586 1000 587 ) 588 } 589 } 590 }) 591 592 //-- Smooth scrolling to the top of page 593 $('#scroll-top').click(function () { 594 $('html, body').animate( 595 { 596 scrollTop: 0, 597 }, 598 500 599 ) 600 }) 601 602 //-- Tootips plugin init 603 tippy('.tippy', { 604 arrow: false, 605 animation: 'shift-away-subtle', 606 }) 607 608 //-- Add class on nav when you scroll over XXXpx 609 $(window).scroll(function () { 610 if ($(this).scrollTop() > 100) { 611 $('nav').addClass('scroll') 612 } else { 613 $('nav').removeClass('scroll') 614 } 615 }) 616 617 scrollTo(document.body, 0, 100) 618 document.querySelector('body').style.overflow = 'hidden' 619 620 //-- Browser update 621 var $buoop = { required: { e: -4, f: -3, o: -3, s: -1, c: -3 }, insecure: true, unsupported: true, api: 2021.05 } 622 623 function $buo_f() { 624 var e = document.createElement('script') 625 e.src = '//browser-update.org/update.min.js' 626 document.body.appendChild(e) 627 } 628 try { 629 document.addEventListener('DOMContentLoaded', $buo_f, false) 630 } catch (e) { 631 window.attachEvent('onload', $buo_f) 632 } 633} 634 635//------------------------------------- 636// RESPONSIVE 637//------------------------------------- 638const responsive = () => { 639 // Add debouncing to prevent rapid recalculations 640 clearTimeout(window.resizeTimeout) 641 window.resizeTimeout = setTimeout(() => { 642 // Reset any width constraints before recalculating 643 if (nav_horizontal_left) { 644 if (d.q('.nav .nav-items-wrap')) d.q('.nav .nav-items-wrap').style.width = 'auto' 645 if (d.q('.nav .homelink')) d.q('.nav .homelink').style.width = 'auto' 646 } 647 if (nav_horizontal_right) { 648 if (d.q('.nav .homelink')) d.q('.nav .homelink').style.width = 'auto' 649 } 650 651 // Recalculate navigation display 652 if (nav_horizontal_right_left || nav_horizontal_center) display_burger_icon() 653 if (nav_horizontal_center && page_name == 'menus') sticky_menu_nav() 654 if (nav_horizontal_right_left || nav_horizontal_center || nav_vertical) remove_buttons_menu() 655 if (nav_inside || (nav_vertical && 750 >= window.innerWidth)) remove_burger_menu() 656 if (nav_vertical) d.q('.nav-items-wrap').style.height = 'calc(100% - ' + d.q('.nav__bottom').scrollHeight + 'px)' 657 658 // Apply width adjustments after navigation state is determined 659 adjust_nav_widths() 660 661 if (nav_vertical) { 662 if (768 >= window.innerWidth) { 663 d.q('.header-vertical .homelink').style.width = 664 'calc(100% - ' + d.q('.header-vertical .nav__buttons').scrollWidth + 'px)' 665 } else { 666 d.q('.header-vertical .homelink').style.width = 'auto' 667 } 668 } else if (nav_inside) { 669 if (768 >= window.innerWidth) { 670 d.q('.nav-inside .homelink').style.width = 671 'calc(100% - ' + d.q('.nav-inside .burger-button').scrollWidth + 'px)' 672 } else { 673 d.q('.nav-inside .homelink').style.width = 'auto' 674 } 675 } 676 677 //-- Resize menus summary on screen resize 678 for (let j = 0; j < d.qAll('.menu-wrap').length; j++) { 679 if (d.qAll('.menu-wrap')[j].classList.contains('active')) { 680 d.q('.menus-wrapper').style.height = d.qAll('.menu-wrap')[j].offsetHeight + 'px' 681 } 682 } 683 }, 150) 684} 685 686//------------------------------------- 687// VARIABLES 688//------------------------------------- 689var d = document 690d.q = document.querySelector 691d.qAll = document.querySelectorAll 692 693var page_name = d.q('body').className.split('current-page-')[1].split(' ')[0] 694 695var template_w_slider = template == 0 || template == 7 || template == 8 || template == 9 696 697var nav_horizontal_right = 698 template == 1 || 699 template == 4 || 700 template == 11 || 701 template == 15 || 702 template == 16 || 703 template == 17 || 704 template == 18 || 705 template == 19 706var nav_horizontal_left = template == 7 707 708var nav_horizontal_right_left = nav_horizontal_right + nav_horizontal_left 709 710var nav_horizontal_center = template == 8 711var nav_vertical = template == 2 || template == 5 || template == 9 712var nav_inside = template == 3 || template == 6 713 714//-- Init variables for nav 715var nav_btns_width = 0 716var nav_dropdown_lang_width = 0 717var homelink_width = 0 718var nav_width = 0 719var nav_mobile_width = 0 720var initial_nav_mobile_width = 0 // Store the initial calculation 721var nav_height_max = 0 // For nav_horizontal_center 722 723// Initialize navigation measurements after DOM is ready 724const initialize_nav_measurements = () => { 725 if (nav_vertical) { 726 let header_padding_side = 727 parseInt(getComputedStyle(d.q('header')).paddingLeft) + parseInt(getComputedStyle(d.q('header')).paddingRight) 728 729 let number_of_btns = 0 730 let btn_margin = 0 731 nav_btns_width = 0 732 733 if (d.q('header .buttons-wrap-header .btn')) { 734 number_of_btns = d.qAll('header .buttons-wrap-header .btn').length 735 btn_margin = parseInt(getComputedStyle(d.q('header .buttons-wrap-header .btn')).marginRight) || 0 736 for (let n = 0; n < number_of_btns; n++) 737 nav_btns_width = nav_btns_width + d.qAll('header .buttons-wrap-header .btn')[n].scrollWidth 738 nav_btns_width = nav_btns_width + btn_margin * number_of_btns 739 } 740 741 nav_mobile_width = d.q('header .homelink').scrollWidth + nav_btns_width + 54 + header_padding_side 742 initial_nav_mobile_width = nav_mobile_width 743 } 744 745 if (nav_horizontal_center) { 746 var nav_padding = 747 parseInt(getComputedStyle(d.q('nav')).paddingTop) + parseInt(getComputedStyle(d.q('nav')).paddingBottom) 748 var item_margin = 749 parseInt(getComputedStyle(d.q('nav .nav__item')).marginTop) + 750 parseInt(getComputedStyle(d.q('nav .nav__item')).marginBottom) 751 752 let nav_btns_width = 0 753 let nav_btn_height = 0 754 if (d.q('.nav__items .btn')) { 755 nav_btn_height = d.q('.nav__items .btn').offsetHeight 756 for (let n = 0; n < d.qAll('.nav__items .btn').length; n++) 757 nav_btns_width = nav_btns_width + d.qAll('.nav__items .btn')[n].scrollWidth 758 } 759 760 nav_height_max = 761 (d.q('nav .nav__item').clientHeight + item_margin) * 2 + (nav_btn_height + item_margin) + nav_padding 762 763 // Get homelink width if not already set 764 if (homelink_width === 0 && d.q('.homelink')) { 765 homelink_width = d.q('.homelink').scrollWidth 766 } 767 768 nav_mobile_width = homelink_width + nav_btns_width + 80 + 54 + 40 769 initial_nav_mobile_width = nav_mobile_width 770 } 771 772 // For horizontal nav, calculate initial values 773 if (nav_horizontal_right_left) { 774 calculate_nav_width() 775 } 776} 777 778// Ensure DOM is ready before running main 779if (document.readyState === 'loading') { 780 document.addEventListener('DOMContentLoaded', main) 781} else { 782 // DOM is already ready, call main immediately 783 main() 784} 785 786window.addEventListener('resize', responsive) 787 788// Recalculate nav width when fonts are loaded 789if (document.fonts && document.fonts.ready) { 790 document.fonts.ready.then(() => { 791 // Reinitialize only if initial_nav_mobile_width wasn't set properly 792 if (initial_nav_mobile_width === 0) { 793 initialize_nav_measurements() 794 } 795 if (nav_horizontal_right_left || nav_horizontal_center) { 796 setTimeout(() => { 797 display_burger_icon() 798 }, 100) 799 } 800 }) 801} 802 803// Also recalculate on window load (for images and other resources) 804window.addEventListener('load', () => { 805 // Reinitialize only if initial_nav_mobile_width wasn't set properly 806 if (initial_nav_mobile_width === 0) { 807 initialize_nav_measurements() 808 } 809 if (nav_horizontal_right_left || nav_horizontal_center) { 810 setTimeout(() => { 811 display_burger_icon() 812 }, 100) 813 } 814}) 815 816// Additional safeguard - recalculate after a short delay 817setTimeout(() => { 818 // Final attempt to initialize if still not set 819 if (initial_nav_mobile_width === 0) { 820 initialize_nav_measurements() 821 } 822 if (nav_horizontal_right_left || nav_horizontal_center) { 823 display_burger_icon() 824 } 825}, 500) 826 827//------------------------------------- 828// ACCESSIBILITY - Keyboard Navigation 829//------------------------------------- 830 831// Focus trap for modal dialogs (burger menu) 832const getFocusableElements = (container) => { 833 if (!container) return [] 834 return Array.from(container.querySelectorAll( 835 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not
835([tabindex="-1"])' 836 )).filter(el => el.offsetParent !== null) // Only visible elements 837} 838 839const trapFocus = (e, container) => { 840 const focusableElements = getFocusableElements(container) 841 if (focusableElements.length === 0) return 842 843 const firstElement = focusableElements[0] 844 const lastElement = focusableElements[focusableElements.length - 1] 845 846 if (e.shiftKey && document.activeElement === firstElement) { 847 // Shift+Tab on first element -> go to last 848 e.preventDefault() 849 lastElement.focus() 850 } else if (!e.shiftKey && document.activeElement === lastElement) { 851 // Tab on last element -> go to first 852 e.preventDefault() 853 firstElement.focus() 854 } 855} 856 857// Add keyboard support for burger button 858document.addEventListener('keydown', function (e) { 859 // Handle Enter or Space on burger button 860 if (e.target.classList.contains('burger-button')) { 861 if (e.key === 'Enter' || e.key === ' ') { 862 e.preventDefault() 863 display_burger_menu() 864 // Focus first focusable element in menu after opening 865 setTimeout(() => { 866 const burgerMenu = d.q('.burger-menu.show') || d.q('.nav-vertical.show') 867 if (burgerMenu) { 868 const focusable = getFocusableElements(burgerMenu) 869 if (focusable.length > 0) { 870 focusable[0].focus() 871 } 872 } 873 }, 100) 874 } 875 } 876 877 // Handle Enter or Space on dropdown icons in burger menu 878 if (e.target.classList.contains('fa-angle-down') && e.target.hasAttribute('role')) { 879 if (e.key === 'Enter' || e.key === ' ') { 880 e.preventDefault() 881 display_burger_dropdown(e.target) 882 } 883 } 884 885 // Handle Tab key for focus trap in burger menu 886 if (e.key === 'Tab') { 887 const burgerMenu = d.q('.burger-menu') 888 const navVertical = d.q('.nav-vertical') 889 if (burgerMenu && burgerMenu.classList.contains('show')) { 890 trapFocus(e, burgerMenu) 891 } else if (navVertical && navVertical.classList.contains('show')) { 892 trapFocus(e, navVertical) 893 } 894 } 895 896 // Handle Escape key to close burger menu 897 if (e.key === 'Escape') { 898 const burgerMenu = d.q('.burger-menu') 899 const navVertical = d.q('.nav-vertical') 900 if ((burgerMenu && burgerMenu.classList.contains('show')) || 901 (navVertical && navVertical.classList.contains('show'))) { 902 remove_burger_menu() 903 // Return focus to burger button 904 const burgerBtn = d.q('.burger-button') 905 if (burgerBtn) { 906 burgerBtn.focus() 907 } 908 } 909 } 910})
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.