1console.log("Megamenu script loaded"); 2 3// megamenu renderer 4function renderSimpleMenu($placeholder, menuJson) { 5 if (!$placeholder || !menuJson || !menuJson.length) return; 6 7 const $ul = $('<ul>', { 8 class: 'list-unstyled fs-14 fw-500 text-decoration-underline column-2' 9 }); 10 11 $.each(menuJson, function(_, item) { 12 if (item.noLink) return; 13 14 let title = decodeURIComponent(item.title || '') 15 .replace(/\s*\(.*?\)\s*/g, '') 16 .trim(); 17 18 const $li = $('<li>', { class: 'mt-24 mt-lg-32' }); 19 20 const $a = $('<a>', { 21 class: 'header-nav-link', 22 href: item.href || '#', 23 text: title 24 }); 25 26 $li.append($a); 27 $ul.append($li); 28 }); 29 30 $placeholder.empty().append($ul); 31} 32 33// megamenu two column renderer 34function safeDecodeMenuTitle(str) { 35 str = String(str || ''); 36 37 try { 38 return decodeURIComponent(str); 39 } catch (e) { 40 // fallback for broken latin1/cp1252-style percent encoding like %EB 41 return str.replace(/%([0-9A-Fa-f]{2})/g, function(match, hex) { 42 return String.fromCharCode(parseInt(hex, 16)); 43 }); 44 } 45} 46 47function cleanMenuTitle(title) { 48 return safeDecodeMenuTitle(title) 49 .replace(/\s*\(.*?\)\s*/g, '') 50 .trim(); 51} 52 53function splitIntoColumns(items, columnCount) { 54 const result = []; 55 const total = items.length; 56 57 const baseSize = Math.floor(total / columnCount); 58 const remainder = total % columnCount; 59 60 let start = 0; 61 62 for (let i = 0; i < columnCount; i++) { 63 const extra = i < remainder ? 1 : 0; 64 const end = start + baseSize + extra; 65 66 result.push(items.slice(start, end)); 67 start = end; 68 } 69 70 return result; 71} 72 73function renderMenuColumns($placeholder, menuJson, options) { 74 if (!$placeholder?.length || !menuJson?.length) return; 75 76 const settings = $.extend({ 77 title: '', 78 columns: 2, 79 colClasses: [ 80 'col-6 col-md-4 col-lg-3', 81 'col-6 col-md-3 col-lg-2 ps-lg-5' 82 ], 83 headingClass: 'fs-14 fw-500 mb-4 d-none d-md-block d-lg-none d-xl-block', 84 ulClass: 'list-unstyled fs-14 fw-500 text-decoration-underline', 85 firstLiClass: 'mt-8 mt-md-16 mt-lg-24', 86 liClass: 'mt-16 mt-md-24', 87 linkClass: 'header-nav-link' 88 }, options || {}); 89 90 const items = $.grep(menuJson, item => !item.noLink); 91 92 const columns = splitIntoColumns(items, settings.columns); 93 94 $placeholder.empty(); 95 96 $.each(columns, function(colIndex, columnItems) { 97 const colClass = settings.colClasses[colIndex] || 'col'; 98 const headingText = colIndex === 0 ? settings.title : ' '; 99 100 const $col = $('<div>', { class: colClass }); 101 102 const $heading = $('<h2>', { 103 class: settings.headingClass, 104 html: headingText 105 }); 106 107 const $ul = $('<ul>', { class: settings.ulClass }); 108 109 $.each(columnItems, function(itemIndex, item) { 110 const $li = $('<li>', { 111 class: itemIndex === 0 ? settings.firstLiClass : settings.liClass 112 }); 113 114 const $a = $('<a>', { 115 class: settings.linkClass, 116 href: item.href || '#', 117 text: cleanMenuTitle(item.title) 118 }); 119 120 $li.append($a); 121 $ul.append($li); 122 }); 123 124 $col.append($heading).append($ul); 125 $placeholder.append($col); 126 }); 127} 128 129//GSAP és multi menu 130//Mobilon áthelyezzük a menüt: 131if ($(window).width() < 1200) { 132 $("#main-nav-BS-helye").append($("#main-nav-BS")); 133} 134 135//MULTI MENUS (submenük) 136$(document).ready(function() { 137 const $nav = $("#main-nav-BS"); 138 const $mobileTarget = $("#main-nav-BS-helye"); 139 const $desktopTarget = $("#main-nav-BS-origin"); 140 141 function checkWidth() { 142 const windowWidth = $(window).width(); 143 144 if (windowWidth < 1200) { 145 // Ha mobil nézet és még nincs a mobil helyén, áttesszük 146 if ($nav.parent().attr('id') !== 'main-nav-BS-helye') { 147 $mobileTarget.append($nav); 148 } 149 } else { 150 // Ha 1200 felett vagyunk, és még a mobil helyén van, visszatesszük az eredeti helyére 151 if ($nav.parent().attr('id') === 'main-nav-BS-helye') { 152 $desktopTarget.append($nav); 153 154 // Opcionális: Ha asztalin nem kell a GSAP transform, töröljük le róla 155 gsap.set($nav, { clearProps: "all" }); 156 } 157 } 158 } 159 160 // Futtatás betöltéskor (DOM ready után) 161 checkWidth(); 162 163 // Futtatás minden átméretezéskor (resize) 164 $(window).on('resize', function() { 165 checkWidth(); 166 }); 167 168 function openMenu(menu, menuClass = '') { 169 const $targetMenu = $(menu); 170 const $otherMenus = $('.multi-menu').not($targetMenu);
171 const $overlay = $('#menu-overlay'); 172 173 // 1. Többi menü bezárása (ha nyitva lenne bármelyik) 174 if ($otherMenus.is(':visible')) { 175 gsap.to($otherMenus, { 176 duration: 0.3, 177 height: 0, 178 opacity: 0, 179 display: 'none', 180 ease: "power2.inOut" 181 }); 182 } 183 184 // 2. Logika: Nyitás vagy Csukás? 185 if ($targetMenu.is(':visible')) { 186 // CSUKÁS 187 gsap.to($targetMenu, { 188 duration: 0.4, 189 height: 0, 190 opacity: 0, 191 ease: "power2.inIn", 192 onComplete: () => $targetMenu.hide() 193 }); 194 195 gsap.to($overlay, { 196 duration: 0.4, 197 opacity: 0, 198 display: 'none' 199 }); 200 201 // if ($(window).width() < 1200) { 202 // gsap.set($('#offerte-mobile-fixed'), { x: "-100%" }); 203 // } 204 } else { 205 // NYITÁS 206 const isMobile = $(window).width() < 1200; 207 208 // Reset layer 3 if re-opening the alle menu 209 if (menu === '#multi-menu-alle') { 210 gsap.set($('#mega-layer3'), { display: 'none' }); 211 $targetMenu.find('.row.gx-lg-5').show(); 212 } 213 214 // Alapbeállítások (közös) 215 gsap.set($targetMenu, { 216 display: 'block', 217 height: 0, 218 opacity: 0, 219 overflowY: 'hidden', 220 }); 221 222 // Dinamikus célértékek meghatározása 223 const offerteH = isMobile ? (200 || 120) : 0; 224 const targetH = isMobile ? $(window).height() - 100 : 462; 225 226 gsap.to($targetMenu, { 227 duration: 0.6, 228 height: targetH, 229 opacity: 1, 230 ease: "expo.out", 231 onComplete: function() { 232 gsap.set($targetMenu, { 233 overflowY: 'scroll', 234 webkitOverflowScrolling: 'touch', 235 maxHeight: targetH, 236 paddingBottom: isMobile ? offerteH : 0 237 }); 238 } 239 }); 240 241 gsap.to($overlay, { 242 duration: 0.5, 243 display: 'block', 244 opacity: 1, // Feltételezve, hogy a CSS-ben az alap opacity pl. 0.5 vagy 1 245 ease: "power2.out" 246 }); 247 248 // if (isMobile) { 249 // gsap.set($('#offerte-mobile-fixed'), { x: "0%" }); 250 // } 251 if (isMobile) { 252 if (menu === '#multi-menu-search') { 253 gsap.set($('#offerte-mobile-fixed'), { x: '-100%' }); 254 } else { 255 setOfferteLayer(2); 256 } 257 } 258 259 // adjust menu height on mobile 260 if ($(window).width() < 800 && menuClass != '' && !$(menuClass).hasClass('mega-calculated-height')) { 261 // console.log("Adjusting mega menu height for mobile " + menuClass + ", targetH " + targetH); 262 // console.log("offerteH: " + offerteH); 263 // console.log("Current mega menu height: " + $(menuClass).height()); 264 // console.log("Calculated new height: " + ($(menuClass).height() - (targetH - $(menuClass).height()) - $(menuClass).height())); 265 266 var myOffset = 25; 267 if (menuClass === '.mega-informatie') myOffset = -25; 268 269 $(menuClass).height($(menuClass).height() + (targetH - $(menuClass).height()) - $(menuClass).height() - myOffset); 270 $(menuClass).css('overflow-y', 'scroll'); 271 $(menuClass).addClass('mega-calculated-height'); 272 } 273 } 274 } 275 276 // Close helpers (desktop only) 277 let menuCloseTimer = null; 278 279 function closeAllMenus() { 280 const $visibleMenus = $('.multi-menu:visible'); 281 if (!$visibleMenus.length) return; 282 gsap.to($visibleMenus, { 283 duration: 0.3, 284 height: 0, 285 opacity: 0, 286 ease: "power2.inOut", 287 onComplete: () => $visibleMenus.hide() 288 }); 289 gsap.to($('#menu-overlay'), { 290 duration: 0.3, 291 opacity: 0, 292 display: 'none' 293 }); 294 setOfferteLayer(1); 295 } 296 297 function scheduleMenuClose() { 298 if ($(window).width() < 1200) return; 299 clearTimeout(menuCloseTimer); 300 menuCloseTimer = setTimeout(closeAllMenus, 150); 301 } 302 303 function cancelMenuClose() { 304 clearTimeout(menuCloseTimer); 305 } 306 307 // MEGAMENU triggers 308 $('#custom-menu-trigger').on('click mouseenter', function (e) { 309 if (e.type === 'mouseenter' && $(window).width() < 1200) return; 310 cancelMenuClose(); 311 if (e.type === 'mouseenter' && $('#multi-menu-alle').is(':visible')) return; 312 e.preventDefault(); 313 e.stopPropagation(); 314 openMenu('#multi-menu-alle'); 315 }); 316 $('#custom-menu-trigger').closest('li').on('mouseleave', scheduleMenuClose); 317 318 $('#custom-menu-trigger-info').on('click mouseenter', function (e) { 319 if (e.type === 'mouseenter' && $(window).width() < 1200) return; 320 cancelMenuClose(); 321 if (e.type === 'mouseenter' && $('#multi-menu-informatie').is(':visible')) return; 322 e.preventDefault(); 323 e.stopPropagation(); 324 openMenu('#multi-menu-informatie', '.mega-informatie'); 325 }); 326 $('#custom-menu-trigger-info').closest('li').on('mouseleave', scheduleMenuClose); 327 328 $('#custom-menu-trigger-tonzon').on('click mouseenter', function (e) { 329 if (e.type === 'mouseenter' && $(window).width() < 1200) return; 330 cancelMenuClose(); 331 if (e.type === 'mouseenter' && $('#multi-menu-tonzon').is(':visible')) return; 332 e.preventDefault(); 333 e.stopPropagation(); 334 openMenu('#multi-menu-tonzon', '.mega-tonzon'); 335 }); 336 $('#custom-menu-trigger-tonzon').closest('li').on('mouseleave', scheduleMenuClose); 337 338 $('.custom-menu-trigger-search').on('click', function (e) { 339 // if (e.type === 'mouseenter' && $(window).width() < 1200) return; 340 cancelMenuClose(); 341 // if (e.type === 'mouseenter' && $('#multi-menu-search').is(':visible')) return; 342 e.preventDefault(); 343 e.stopPropagation(); 344 openMenu('#multi-menu-search'); 345 }); 346 $('.custom-menu-trigger-search').closest('li').on('mouseleave', scheduleMenuClose); 347 348 // Keep menus open when hovering over the panel itself 349 $('#multi-menu-alle, #multi-menu-informatie, #multi-menu-tonzon, #multi-menu-search') 350 .on('mouseenter', cancelMenuClose) 351 .on('mouseleave', scheduleMenuClose); 352 353 $('.link-back').on('click', function (e) { 354 e.preventDefault(); 355 e.stopPropagation(); 356 $('.multi-menu').slideUp(200);
357 $('#menu-overlay').slideUp(300); 358 setOfferteLayer(1); 359 }); 360 361 $(document).on('click', function (e) { 362 if (!$(e.target).closest('.multi-menu').length) { 363 $('.multi-menu').slideUp(200); 364 $('#menu-overlay').slideUp(300); 365 setOfferteLayer(1); 366 } 367 }); 368 369 //MAIN NAV (fõmenü) 370 // const $nav = $('#main-nav-BS'); 371 const $body = $('body'); 372 const $offerte = $('#offerte-mobile-fixed'); 373 374 $nav.on('show.bs.collapse', function(e) { 375 //e.preventDefault(); 376 377 $body.addClass('menu-open'); 378 $nav.addClass('show'); 379 380 // Elõször láthatóvá tesszük, de még kint van 381 gsap.set($nav, { visibility: 'visible' }); 382 383 // Beúsztatás a 0-ás pontra (a képernyõ bal széle) 384 gsap.to($nav, { 385 duration: 0.6, 386 x: "0%", // Bejön a helyére 387 ease: "expo.out", 388 overwrite: true 389 }); 390 gsap.to($offerte, { 391 duration: 0.6, 392 x: "0%", // Bejön a helyére 393 ease: "expo.out", 394 overwrite: true 395 }); 396 397 }); 398 399 $nav.on('hide.bs.collapse', function(e) { 400 //e.preventDefault(); 401 402 gsap.to($nav, { 403 duration: 0.5, 404 x: "-100%", // Teljesen kimegy balra 405 ease: "power2.in", 406 onComplete: function() { 407 $nav.removeClass('show'); 408 $nav.css('visibility', 'hidden'); 409 $body.removeClass('menu-open'); 410 } 411 }); 412 gsap.to($offerte, { 413 duration: 0.5, 414 x: "-100%", // Teljesen kimegy balra 415 ease: "power2.in" 416 }); 417 }); 418}); 419 420// render menu's START 421// renderSimpleMenu($('.mega-vloerisolatie'), params_1165.menuJson); 422renderMenuColumns($('.mega-vloerisolatie'), mega_vloerisolatie, { 423 title: '', 424 columns: 2, 425 colClasses: [ 426 'col-6', 427 'col-6' 428 ], 429 headingClass: 'd-none', 430 linkClass: 'header-nav-link lh-140' 431}); 432renderSimpleMenu($('.mega-muurisolatie'), mega_muurisolatie); 433renderSimpleMenu($('.mega-dakisolatie'), mega_dakisolatie); 434renderSimpleMenu($('.mega-cv-isolatie'), mega_cvisolatie); 435 436renderMenuColumns($('.mega-informatie'), mega_informatie, { 437 title: 'Meer informatie', 438 columns: 2, 439 colClasses: [ 440 'col-12 col-lg-6', 441 'col-12 col-lg-6 mt-8 mt-lg-0' 442 ], 443}); 444 445renderMenuColumns($('.mega-tonzon'), mega_tonzon, { 446 title: 'Over Tonzon', 447 columns: 2, 448 colClasses: [ 449 'col-12 col-lg-6', 450 'col-12 col-lg-6 mt-8 mt-lg-0' 451 ], 452}); 453 454// render menu's END 455 456// Mobile layer 3 ? opens category detail within #multi-menu-alle 457function setOfferteLayer(n) { 458 if ($(window).width() >= 1200) return; 459 const $o = $('#offerte-mobile-fixed'); 460 $o.find('.review-block').toggleClass('d-none', n !== 1); 461 $o.find('.shop-card').toggleClass('d-none', n !== 2); 462 $o.find('.faq-card').toggleClass('d-none', n !== 3); 463 464 // show shop and faq above 800px on layer 2 and 3 465 if ($(window).width() > 800 && n > 1) { 466 $o.find('.shop-card').removeClass('d-none'); 467 $o.find('.faq-card').removeClass('d-none'); 468 } 469} 470 471function showMegaLayer3(target, title) { 472 let $layer3 = $('#mega-layer3'); 473 if (!$layer3.length) { 474 $layer3 = $('<div>', { id: 'mega-layer3', class: 'px-10 pt-0' }); 475 $layer3.append( 476 $('<div>', { class: 'mb-16' }).append( 477 $('<a>', { 478 href: '#', 479 class: 'f-14 color-2 link-reverse link-back-layer2', 480 html: '<i class="ico ico-arrow-start"></i>Ga terug' 481 }) 482 ), 483 $('<h2>', { id: 'mega-layer3-title', class: 'fs-22 fw-500 mt-10 mb-0' }), 484 $('<p>', { class: 'fs-14 fw-500 mt-24 mb-0', text: 'Meer over' }), 485 $('<div>', { id: 'mega-layer3-links' }) 486 ); 487 $('#multi-menu-alle .container-lg').append($layer3); 488 gsap.set($layer3, { display: 'none' }); 489 } 490 491 // Build a flat link list from the target mega-item 492 const $megaItem = $('.mega-item.mega-' + target); 493 const $ul = $('<ul>', { class: 'list-unstyled fs-14 fw-500 text-decoration-underline' }); 494 $megaItem.find('a').each(function () { 495 $('<li>', { class: 'mt-22' }).append( 496 $('<a>', { class: 'header-nav-link', href: $(this).attr('href'), text: $(this).text() }) 497 ).appendTo($ul); 498 }); 499 500 $('#mega-layer3-title').text(title); 501 $('#mega-layer3-links').html($ul); 502 503 $('#multi-menu-alle .row.gx-lg-5').hide(); 504 gsap.set($layer3, { display: 'block', opacity: 0, x: 30 }); 505 gsap.to($layer3, { opacity: 1, x: 0, duration: 0.3, ease: 'power2.out' }); 506 setOfferteLayer(3); 507} 508 509function hideMegaLayer3() { 510 const $layer3 = $('#mega-layer3'); 511 if (!$layer3.length || $layer3.css('display') === 'none') return; 512 gsap.to($layer3, { 513 opacity: 0, x: -30, duration: 0.25, ease: 'power2.in', 514 onComplete: function () { 515 gsap.set($layer3, { display: 'none', x: 0 }); 516 $('#multi-menu-alle .row.gx-lg-5').show(); 517 setOfferteLayer(2); 518 } 519 }); 520} 521 522$(document).on('click', '.link-back-layer2', function (e) { 523 e.preventDefault(); 524 e.stopPropagation(); 525 hideMegaLayer3(); 526}); 527 528// mega selector on click and mouseenter 529$(document).on("mouseenter", ".mega-selector", function (e) { 530 e.preventDefault(); 531 532 $(".mega-selector").removeClass("active"); 533 $(this).addClass("active"); 534 535 var target = $(this).attr("href").replace(/^\/|\/$/g, ''); 536 console.log("Mega selector clicked: " + target); 537 538 // Mobile tap: open layer 3 539 if (e.type === 'click' && $(window).width() < 1200) { 540 var title = $(this).find('span').first().text().trim(); 541 showMegaLayer3(target, title); 542 return; 543 } 544 545 // Ignore mouseenter on mobile 546 if (e.type === 'mouseenter' && $(window).width() < 1200) return; 547 548 // Desktop: switch the visible mega-item panel 549 if ($(".mega-item.mega-" + target).not(".d-none").length > 0) { 550 return; 551 } 552 553 $(".mega-item").stop(true, true); 554
555 $(".mega-item:not(.d-none)").slideUp(150, function() { 556 $(this).addClass("d-none").removeAttr("style"); 557 $(".mega-item.mega-" + target).removeClass("d-none").hide().slideDown(300); 558 }); 559});
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.