Prodejna / Showroom
nám. Komenského 78, FULNEK 742 45
Neváhejte nás kontaktovat
Zuzana Novotná
Po - Pá: 8:00 - 16:00
/* ========================================================================
GARNYZE24.CZ
DESKTOP MEGA MENU V4
========================================================================
DŮLEŽITÉ:
- NEVÁŽE listenery na konkrétní LI při načtení
- funguje i když Eshop-rychle menu později přegeneruje
- používá event delegation
- původní menu slouží jako zdroj URL, názvů a obrázků
- nový panel se vytváří přímo v BODY
- desktop od 1100 px
======================================================================== */
(function () {
'use strict';
var DESKTOP_MIN = 1100;
var OPEN_DELAY = 70;
var CLOSE_DELAY = 350;
var openTimer = null;
var closeTimer = null;
var activeItem = null;
var activeTrigger = null;
var activePanel = null;
var overlay = null;
var panelCache = new Map();
/* =====================================================================
KONFIGURACE
===================================================================== */
var CONFIG = {
'/kovove-garnyze-jednorade': {
kicker: 'Jedna řada',
title: 'Jednořadé garnýže',
description:
'Pro záclonu nebo závěs. Vyberte si moderní, cenově výhodné, hranaté, barokní nebo garnýže s drážkou.',
allLabel:
'Všechny jednořadé garnýže',
middleTitle:
'Vyberte typ garnýže',
middleNote:
'Jedna řada pro záclonu nebo závěs',
helpTitle:
'Jak vybrat správnou garnýž?',
helpText:
'Poradíme s délkou, průměrem tyče, konzolami i správným přesahem přes okno.'
},
'/kovove-garnyze-dvourade': {
kicker: 'Dvě řady',
title: 'Dvouřadé garnýže',
description:
'Ideální pro kombinaci záclony a závěsu. Porovnejte jednotlivé průměry, styly a konstrukční varianty.',
allLabel:
'Všechny dvouřadé garnýže',
middleTitle:
'Vyberte typ garnýže',
middleNote:
'Záclona a závěs v jednom systému',
helpTitle:
'Jak vybrat dvouřadou garnýž?',
helpText:
'Pomůžeme zvolit vhodnou délku, průměry tyčí i správný rozestup jednotlivých řad.'
},
'/stropni-garnyze': {
kicker: 'Montáž do stropu',
title: 'Stropní garnýže',
description:
'Řešení pro montáž garnýže přímo do stropu. Vhodné tam, kde není možné nebo žádoucí upevnění na stěnu.',
allLabel:
'Všechny stropní garnýže',
middleTitle:
'Vyberte provedení',
middleNote:
'Kulaté i hranaté stropní systémy',
helpTitle:
'Kdy zvolit montáž do stropu?',
helpText:
'Zjistěte, zda je pro vaše okno vhodnější montáž na stěnu, nebo přímo do stropu.'
},
'/prislusenstvi-ke-garnyzim': {
kicker: 'Komponenty',
title: 'Příslušenství ke garnýžím',
description:
'Tyče, konzoly, koncovky a další díly pro doplnění, rozšíření nebo opravu garnýžového systému.',
allLabel:
'Všechno příslušenství',
middleTitle:
'Vyberte typ systému',
middleNote:
'Komponenty podle typu garnýže',
helpTitle:
'Nevíte, který díl potřebujete?',
helpText:
'Pomůžeme najít správnou konzolu, koncovku, tyč nebo další kompatibilní komponent.'
}
};
/* =====================================================================
HELPERY
===================================================================== */
function isDesktop() {
return window.innerWidth >= DESKTOP_MIN;
}
function cleanText(text) {
return (text || '')
.replace(/\s+/g, ' ')
.trim();
}
function normalizePath(href) {
if (!href) {
return '';
}
try {
var url = new URL(
href,
window.location.origin
);
return (
url.pathname.replace(/\/+$/, '')
|| '/'
);
} catch (e) {
return href;
}
}
function create(tag, cls, text) {
var node =
document.createElement(tag);
if (cls) {
node.className = cls;
}
if (
text !== undefined &&
text !== null
) {
node.textContent = text;
}
return node;
}
function makeLink(cls, href, text) {
var node =
create('a', cls, text);
node.href = href || '#';
return node;
}
function directChild(parent, selector) {
if (!parent) {
return null;
}
for (
var i = 0;
i < parent.children.length;
i++
) {
if (
parent.children[i]
.matches(selector)
) {
return parent.children[i];
}
}
return null;
}
/* =====================================================================
NAJDE AKTUÁLNÍ ROOT MENU
===================================================================== */
function getMenuRoot() {
return document.querySelector(
'#eshop-menu-wrapper'
);
}
/*
* Nezáleží na interních event listenerech.
* Z targetu zjistíme aktuální hlavní LI.
*/
function getTopItem(target) {
var root =
getMenuRoot();
if (!root || !target) {
return null;
}
var node = target;
while (
node &&
node !== root &&
node !== document.body
) {
if (
node.tagName === 'LI' &&
node.parentElement === root
) {
if (
node.classList.contains(
'c1999'
)
) {
return null;
}
return node;
}
node =
node.parentElement;
}
return null;
}
/* =====================================================================
HLAVNÍ ODKAZ
===================================================================== */
function getTrigger(item) {
if (!item) {
return null;
}
var header =
directChild(
item,
'.c1995'
);
if (!header) {
header =
item.querySelector(
'.c1995'
);
}
if (!header) {
return item.querySelector(
'a[href]'
);
}
return (
header.querySelector(
'a.c1996'
)
||
header.querySelector(
'a[href]'
)
);
}
/* =====================================================================
PŮVODNÍ SUBMENU
===================================================================== */
function getOriginalSubmenu(item) {
if (!item) {
return null;
}
var submenu =
directChild(
item,
'.c2001'
);
if (submenu) {
return submenu;
}
submenu =
item.querySelector(
'.c2001'
);
if (submenu) {
return submenu;
}
/*
* Fallback:
* první vnořené UL,
* které není samotný root.
*/
var lists =
item.querySelectorAll('ul');
for (
var i = 0;
i < lists.length;
i++
) {
if (
lists[i] !== getMenuRoot()
) {
return lists[i];
}
}
return null;
}
/* =====================================================================
OVERLAY
===================================================================== */
function ensureOverlay() {
if (
overlay &&
document.body.contains(overlay)
) {
return overlay;
}
overlay =
document.querySelector(
'.g24-mega-screen'
);
if (overlay) {
return overlay;
}
overlay =
create(
'div',
'g24-mega-screen'
);
overlay.setAttribute(
'aria-hidden',
'true'
);
document.body.appendChild(
overlay
);
overlay.addEventListener(
'mouseenter',
function () {
scheduleClose();
}
);
overlay.addEventListener(
'click',
function () {
closeMenu();
}
);
return overlay;
}
/* =====================================================================
BENEFITY
===================================================================== */
function buildBenefits() {
var wrapper =
create(
'div',
'g24-mega-portal__benefits'
);
[
'Doprava zdarma nad 2 500 Kč bez DPH',
'Vrácení zboží do 30 dnů',
'Showroom a výdejní místo ve Fulneku'
].forEach(
function (text) {
wrapper.appendChild(
create(
'div',
'g24-mega-portal__benefit',
text
)
);
}
);
return wrapper;
}
/* =====================================================================
LEVÝ SLOUPEC
===================================================================== */
function buildIntro(
config,
href
) {
var intro =
create(
'div',
'g24-mega-portal__intro'
);
intro.appendChild(
create(
'span',
'g24-mega-portal__kicker',
config.kicker
)
);
intro.appendChild(
create(
'h2',
'',
config.title
)
);
intro.appendChild(
create(
'p',
'',
config.description
)
);
intro.appendChild(
makeLink(
'g24-mega-portal__all',
href,
config.allLabel
)
);
intro.appendChild(
buildBenefits()
);
return intro;
}
/* =====================================================================
DETEKCE STRUKTURY PODKATEGORIÍ
===================================================================== */
function getCategoryItems(
item,
submenu
) {
var result = [];
/*
* Nejdříve standardní Eshop-rychle.
*/
var list =
submenu
? submenu.querySelector(
'ul.c1993'
)
: null;
if (list) {
Array.prototype
.slice
.call(list.children)
.forEach(
function (li) {
if (
li.tagName === 'LI'
) {
result.push(li);
}
}
);
if (result.length) {
return result;
}
}
/*
* Fallback 1:
* nejbližší UL.
*/
if (submenu) {
var innerList =
submenu.matches('ul')
? submenu
: submenu.querySelector('ul');
if (innerList) {
Array.prototype
.slice
.call(innerList.children)
.forEach(
function (li) {
if (
li.tagName === 'LI'
) {
result.push(li);
}
}
);
if (result.length) {
return result;
}
}
}
/*
* Fallback 2:
* všechny LI uvnitř top item,
* které obsahují obrázek.
*/
item
.querySelectorAll('li')
.forEach(
function (li) {
if (
li.querySelector('img') &&
li.querySelector('a[href]')
) {
result.push(li);
}
}
);
return result;
}
/* =====================================================================
NAJDE NÁZEV KARTY
===================================================================== */
function getCategoryTitle(li) {
var selectors = [
'.c2026 > a.c2004[href]',
'.c2026 a[href]',
'a.c2004[href]',
'a[href]:not(.c2002)'
];
for (
var i = 0;
i < selectors.length;
i++
) {
var link =
li.querySelector(
selectors[i]
);
if (
link &&
cleanText(link.textContent)
) {
return link;
}
}
return li.querySelector(
'a[href]'
);
}
/* =====================================================================
OBRÁZEK
===================================================================== */
function getCategoryImage(li) {
return (
li.querySelector(
'.c2002 img'
)
||
li.querySelector(
'.c1995 img'
)
||
li.querySelector(
'img'
)
);
}
/* =====================================================================
PODODKAZY
===================================================================== */
function getCategorySubLinks(
li,
titleLink
) {
var result = [];
var candidates =
li.querySelectorAll(
'.c2027 a[href], ul a[href]'
);
candidates.forEach(
function (candidate) {
if (
candidate === titleLink
) {
return;
}
var text =
cleanText(
candidate.textContent
);
if (
!text ||
text.toLowerCase() ===
'další'
) {
return;
}
var duplicate =
result.some(
function (existing) {
return (
existing.href ===
candidate.href
);
}
);
if (!duplicate) {
result.push(
candidate
);
}
}
);
return result;
}
/* =====================================================================
KARTA
===================================================================== */
function buildCard(li) {
var title =
getCategoryTitle(li);
if (!title) {
return null;
}
var titleText =
cleanText(
title.textContent
);
if (!titleText) {
return null;
}
var card =
create(
'article',
'g24-mega-portal__card'
);
/* IMAGE */
var imageWrap =
create(
'div',
'g24-mega-portal__image'
);
var imageLink =
document.createElement('a');
imageLink.href =
title.href;
var sourceImage =
getCategoryImage(li);
if (sourceImage) {
var image =
document.createElement('img');
image.src =
sourceImage.currentSrc
||
sourceImage.src
||
sourceImage.getAttribute('src');
image.alt =
sourceImage.alt
||
titleText;
image.loading =
'lazy';
image.decoding =
'async';
imageLink.appendChild(
image
);
}
imageWrap.appendChild(
imageLink
);
card.appendChild(
imageWrap
);
/* BODY */
var body =
create(
'div',
'g24-mega-portal__cardbody'
);
body.appendChild(
makeLink(
'g24-mega-portal__cardtitle',
title.href,
titleText
)
);
var subLinks =
getCategorySubLinks(
li,
title
);
if (subLinks.length) {
var subWrap =
create(
'div',
'g24-mega-portal__links'
);
subLinks.forEach(
function (link) {
subWrap.appendChild(
makeLink(
'',
link.href,
cleanText(
link.textContent
)
)
);
}
);
body.appendChild(
subWrap
);
}
card.appendChild(
body
);
return card;
}
/* =====================================================================
FALLBACK – VŠECHNY ODKAZY
===================================================================== */
function buildFallbackLinks(
item,
trigger,
grid
) {
var seen = {};
item
.querySelectorAll(
'a[href]'
)
.forEach(
function (link) {
if (
link === trigger
) {
return;
}
var text =
cleanText(
link.textContent
);
if (!text) {
return;
}
var href =
link.href;
if (
!href ||
seen[href]
) {
return;
}
seen[href] = true;
var card =
create(
'article',
'g24-mega-portal__card'
);
var body =
create(
'div',
'g24-mega-portal__cardbody'
);
body.appendChild(
makeLink(
'g24-mega-portal__cardtitle',
href,
text
)
);
card.appendChild(body);
grid.appendChild(card);
}
);
}
/* =====================================================================
STŘED
===================================================================== */
function buildMain(
config,
item,
submenu,
trigger
) {
var main =
create(
'div',
'g24-mega-portal__main'
);
var heading =
create(
'div',
'g24-mega-portal__heading'
);
heading.appendChild(
create(
'h3',
'',
config.middleTitle
)
);
heading.appendChild(
create(
'span',
'',
config.middleNote
)
);
main.appendChild(
heading
);
var grid =
create(
'div',
'g24-mega-portal__grid'
);
var categoryItems =
getCategoryItems(
item,
submenu
);
categoryItems.forEach(
function (li) {
var card =
buildCard(li);
if (card) {
grid.appendChild(card);
}
}
);
/*
* Absolutní fallback.
*/
if (
grid.children.length === 0
) {
buildFallbackLinks(
item,
trigger,
grid
);
}
main.appendChild(
grid
);
return main;
}
/* =====================================================================
PRAVÝ SLOUPEC
===================================================================== */
function buildAside(config) {
var aside =
create(
'aside',
'g24-mega-portal__aside'
);
/* PORADNA */
var help =
makeLink(
'g24-mega-portal__help',
'/jak-postupovat-pri-vyberu-garnyze',
''
);
help.appendChild(
create(
'span',
'g24-mega-portal__helpicon',
'?'
)
);
help.appendChild(
create(
'span',
'g24-mega-portal__label',
'Poradna'
)
);
help.appendChild(
create(
'strong',
'',
config.helpTitle
)
);
help.appendChild(
create(
'p',
'',
config.helpText
)
);
aside.appendChild(help);
/* SHOWROOM */
var showroom =
makeLink(
'g24-mega-portal__showroom',
'/showroom',
''
);
var img =
document.createElement('img');
img.src =
'/fotky44333/usp-images/uspImage41602484240.png';
img.alt =
'Showroom Garnýže24.cz ve Fulneku';
img.loading =
'lazy';
showroom.appendChild(img);
var text =
create('div');
text.appendChild(
create(
'span',
'g24-mega-portal__label',
'Showroom'
)
);
text.appendChild(
create(
'strong',
'',
'Prohlédněte si garnýže naživo'
)
);
text.appendChild(
create(
'p',
'',
'Fulnek · Po–Pá 8:00–16:00'
)
);
showroom.appendChild(text);
aside.appendChild(showroom);
return aside;
}
/* =====================================================================
PANEL
===================================================================== */
function buildPanel(
item,
trigger
) {
var path =
normalizePath(
trigger.href
);
var config =
CONFIG[path];
if (!config) {
config = {
kicker:
'Kategorie',
title:
cleanText(
trigger.textContent
),
description:
'Prohlédněte si dostupné varianty této kategorie.',
allLabel:
'Zobrazit celou kategorii',
middleTitle:
'Vyberte podkategorii',
middleNote:
'',
helpTitle:
'Potřebujete poradit?',
helpText:
'Pomůžeme vám vybrat správné řešení.'
};
}
var submenu =
getOriginalSubmenu(
item
);
var panel =
create(
'section',
'g24-mega-portal'
);
/*
* Dáváme jednoznačné ID.
*/
panel.id =
'g24-mega-'
+ path
.replace(
/[^a-z0-9]+/gi,
'-'
)
.replace(
/^-|-$/g,
''
);
panel.setAttribute(
'aria-hidden',
'true'
);
var inner =
create(
'div',
'g24-mega-portal__inner'
);
inner.appendChild(
buildIntro(
config,
trigger.href
)
);
inner.appendChild(
buildMain(
config,
item,
submenu,
trigger
)
);
inner.appendChild(
buildAside(config)
);
panel.appendChild(inner);
document.body.appendChild(
panel
);
/*
* Panel je mimo původní menu,
* takže musíme hlídat hover i zde.
*/
panel.addEventListener(
'mouseenter',
function () {
window.clearTimeout(
closeTimer
);
}
);
panel.addEventListener(
'mouseleave',
function () {
scheduleClose();
}
);
trigger.setAttribute(
'aria-haspopup',
'true'
);
trigger.setAttribute(
'aria-controls',
panel.id
);
panelCache.set(
path,
panel
);
console.log(
'[G24 V4] vytvořen panel:',
path,
'karet:',
panel.querySelectorAll(
'.g24-mega-portal__card'
).length
);
return panel;
}
/* =====================================================================
PANEL PRO AKTUÁLNÍ ITEM
===================================================================== */
function getPanel(
item,
trigger
) {
var path =
normalizePath(
trigger.href
);
/*
* Pokud Eshop-rychle menu přegeneroval,
* panel můžeme ponechat – URL jsou stejná.
*/
if (
panelCache.has(path)
) {
return panelCache.get(path);
}
return buildPanel(
item,
trigger
);
}
/* =====================================================================
POZICE
===================================================================== */
function positionPanel(panel) {
if (!panel) {
return;
}
var root =
getMenuRoot();
if (!root) {
return;
}
var rect =
root.getBoundingClientRect();
/*
* Panel začíná přesně pod produktovou navigací.
*/
var top =
Math.round(
rect.bottom - 1
);
panel.style.top =
top + 'px';
/*
* Overlay začíná až pod menu.
* Header tedy zůstane čistý a klikací.
*/
ensureOverlay();
overlay.style.top =
top + 'px';
}
/* =====================================================================
OPEN
===================================================================== */
function openMenu(
item,
trigger
) {
if (
!isDesktop() ||
!item ||
!trigger
) {
return;
}
window.clearTimeout(openTimer);
window.clearTimeout(closeTimer);
var panel =
getPanel(
item,
trigger
);
if (!panel) {
return;
}
/*
* Předchozí panel.
*/
if (
activePanel &&
activePanel !== panel
) {
activePanel
.classList
.remove('is-open');
activePanel.setAttribute(
'aria-hidden',
'true'
);
}
if (
activeItem &&
activeItem !== item
) {
activeItem
.classList
.remove(
'g24-menu-open'
);
}
if (
activeTrigger &&
activeTrigger !== trigger
) {
activeTrigger.setAttribute(
'aria-expanded',
'false'
);
}
activeItem = item;
activeTrigger = trigger;
activePanel = panel;
positionPanel(panel);
item.classList.add(
'g24-menu-open'
);
trigger.setAttribute(
'aria-expanded',
'true'
);
panel.setAttribute(
'aria-hidden',
'false'
);
panel.classList.add(
'is-open'
);
ensureOverlay();
overlay.setAttribute(
'aria-hidden',
'false'
);
overlay.classList.add(
'is-open'
);
console.log(
'[G24 V4] OPEN:',
normalizePath(trigger.href)
);
}
/* =====================================================================
CLOSE
===================================================================== */
function closeMenu() {
window.clearTimeout(openTimer);
window.clearTimeout(closeTimer);
if (activeItem) {
activeItem
.classList
.remove(
'g24-menu-open'
);
}
if (activeTrigger) {
activeTrigger.setAttribute(
'aria-expanded',
'false'
);
}
if (activePanel) {
activePanel
.classList
.remove(
'is-open'
);
activePanel.setAttribute(
'aria-hidden',
'true'
);
}
if (overlay) {
overlay
.classList
.remove(
'is-open'
);
overlay.setAttribute(
'aria-hidden',
'true'
);
}
activeItem = null;
activeTrigger = null;
activePanel = null;
}
/* =====================================================================
SCHEDULE
===================================================================== */
function scheduleOpen(
item,
trigger
) {
window.clearTimeout(closeTimer);
window.clearTimeout(openTimer);
openTimer =
window.setTimeout(
function () {
/*
* Ověříme, že položka stále existuje.
*/
if (
document.body.contains(item)
) {
openMenu(
item,
trigger
);
}
},
OPEN_DELAY
);
}
function scheduleClose() {
window.clearTimeout(openTimer);
window.clearTimeout(closeTimer);
closeTimer =
window.setTimeout(
function () {
closeMenu();
},
CLOSE_DELAY
);
}
/* =====================================================================
DELEGOVANÝ MOUSEOVER
===================================================================== */
document.addEventListener(
'mouseover',
function (event) {
if (!isDesktop()) {
return;
}
var item =
getTopItem(
event.target
);
if (!item) {
return;
}
/*
* mouseover bublá i mezi dětmi.
* Pokud přecházíme pouze uvnitř stejného LI,
* nic nového neprovádět.
*/
if (
event.relatedTarget &&
item.contains(
event.relatedTarget
)
) {
return;
}
var trigger =
getTrigger(item);
if (!trigger) {
console.warn(
'[G24 V4] trigger nenalezen'
);
return;
}
scheduleOpen(
item,
trigger
);
},
true
);
/* =====================================================================
DELEGOVANÝ MOUSEOUT
===================================================================== */
document.addEventListener(
'mouseout',
function (event) {
if (!isDesktop()) {
return;
}
var item =
getTopItem(
event.target
);
if (!item) {
return;
}
/*
* Stále jsme uvnitř položky.
*/
if (
event.relatedTarget &&
item.contains(
event.relatedTarget
)
) {
return;
}
scheduleClose();
},
true
);
/* =====================================================================
KLIKNUTÍ NA ŠIPKU
===================================================================== */
document.addEventListener(
'click',
function (event) {
if (!isDesktop()) {
return;
}
var arrow =
event.target.closest(
'#eshop-menu-wrapper .c1998'
);
if (!arrow) {
return;
}
var item =
getTopItem(arrow);
if (!item) {
return;
}
var trigger =
getTrigger(item);
if (!trigger) {
return;
}
event.preventDefault();
event.stopPropagation();
if (
activeItem === item &&
activePanel &&
activePanel.classList
.contains('is-open')
) {
closeMenu();
} else {
openMenu(
item,
trigger
);
}
},
true
);
/* =====================================================================
KEYBOARD FOCUS
===================================================================== */
document.addEventListener(
'focusin',
function (event) {
if (!isDesktop()) {
return;
}
var item =
getTopItem(
event.target
);
if (!item) {
return;
}
var trigger =
getTrigger(item);
if (
trigger === event.target
) {
openMenu(
item,
trigger
);
}
}
);
/* =====================================================================
ESC
===================================================================== */
document.addEventListener(
'keydown',
function (event) {
if (
event.key === 'Escape'
) {
closeMenu();
}
}
);
/* =====================================================================
SCROLL
===================================================================== */
window.addEventListener(
'scroll',
function () {
if (
activePanel &&
isDesktop()
) {
positionPanel(
activePanel
);
}
},
{
passive: true
}
);
/* =====================================================================
RESIZE
===================================================================== */
var resizeTimer = null;
window.addEventListener(
'resize',
function () {
window.clearTimeout(
resizeTimer
);
resizeTimer =
window.setTimeout(
function () {
if (!isDesktop()) {
closeMenu();
return;
}
if (activePanel) {
positionPanel(
activePanel
);
}
},
80
);
}
);
/* =====================================================================
WATCHDOG PRO ESHOP-RYCHLE
===================================================================== */
/*
* Eshop-rychle může menu během běhu stránky nahradit.
* Nemusíme znovu registrovat listenery,
* protože používáme delegation.
*
* Observer používáme jen pro diagnostiku.
*/
var observer =
new MutationObserver(
function () {
var root =
getMenuRoot();
if (
root &&
!root.dataset.g24Detected
) {
root.dataset.g24Detected =
'1';
console.log(
'[G24 V4] nové menu Eshop-rychle detekováno'
);
}
}
);
observer.observe(
document.documentElement,
{
childList: true,
subtree: true
}
);
/* =====================================================================
START
===================================================================== */
ensureOverlay();
console.log(
'[G24 V4] SCRIPT AKTIVNÍ'
);
if (getMenuRoot()) {
console.log(
'[G24 V4] #eshop-menu-wrapper nalezen'
);
} else {
console.log(
'[G24 V4] čekám na #eshop-menu-wrapper'
);
}
})();
© 2026 Eshop Garnýže24.cz | Provozovatel: Sortiment 24 s.r.o., Na Trávníkách 959, 742 13 Studénka, ČR
Hlídání ceny
Chci být informován:
Hlídání nastaveno
Budeme vás informovat e-mailem.