function addClass(el,className){ if (el.classList) el.classList.add(className); else el.className += ' ' + className; } function removeClass(el,className){ if (el.classList) el.classList.remove(className); else el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); } function toggleClass(el,className) { if (el.classList) { el.classList.toggle(className); } else { var classes = el.className.split(' '); var existingIndex = classes.indexOf(className); if (existingIndex >= 0) classes.splice(existingIndex, 1); else classes.push(className); el.className = classes.join(' '); } } function hasClass(el,className) { return new RegExp('(\\s|^)'+className+'(\\s|$)').test(el.className); } function getScrollTop() { return window.scrollY || document.documentElement.scrollTop; } function scrollShouldAjaxLoad(el, offset, preset) { offset = offset || 100; preset = preset || false; if(!el) { return false; } try { var windowHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); var r = el.getBoundingClientRect(); if(el.offsetHeight + r.top - offset < windowHeight) { if(preset) { if(el.offsetHeight + r.top + preset > windowHeight) { return true; } return false; } return true; } return false; } catch(e) { return false; } } var smoothScroll = { documentVerticalScrollPosition: function(){ if(self.pageYOffset) return self.pageYOffset; if(document.documentElement && document.documentElement.scrollTop) return document.documentElement.scrollTop; if(document.body.scrollTop) return document.body.scrollTop; return 0; }, viewportHeight: function(){ return (document.compatMode === "CSS1Compat") ? document.documentElement.clientHeight : document.body.clientHeight; }, documentHeight: function(){ return (document.height !== undefined) ? document.height : document.body.offsetHeight; }, documentMaximumScrollPosition: function(){ return this.documentHeight() - this.viewportHeight(); }, elementVerticalClientPosition: function(element){ var rectangle = element.getBoundingClientRect(); return rectangle.top; }, verticalTickToPosition: function(currentPosition, targetPosition){ var filter = 0.2; var fps = 60; var difference = parseFloat(targetPosition) - parseFloat(currentPosition); var arrived = (Math.abs(difference) <= 0.5); if(arrived){ scrollTo(0.0, targetPosition); return; } currentPosition = (parseFloat(currentPosition) * (1.0 - filter)) + (parseFloat(targetPosition) * filter); scrollTo(0.0, Math.round(currentPosition)); var self = this; setTimeout(function(){ self.verticalTickToPosition(currentPosition, targetPosition); }, (1000 / fps)); }, toElement: function(element, padding){ if(!element){ console.warn("Couldn't find target element."); return; } var targetPosition = this.documentVerticalScrollPosition() + this.elementVerticalClientPosition(element) - padding; var currentPosition = this.documentVerticalScrollPosition(); var maximumScrollPosition = this.documentMaximumScrollPosition(); if(targetPosition > maximumScrollPosition) targetPosition = maximumScrollPosition; this.verticalTickToPosition(currentPosition, targetPosition); } }; function Cookie(name, defaultValue, path) { this.name = name; this.value = null; this.path = path || "/"; var ca = document.cookie.split(';'); for(var i=0; i 120) { addClass(body, "shrink"); } else { removeClass(body, "shrink"); } } const NavbarSearchItem_Product = props => { const { data: p, active, highlightIndex, onMouseEnter, } = props; return {p.title}
{p.title}
{p.price} Kč
}; const NavbarSearchItem_Generic = props => { const { data: r, active, highlightIndex, onMouseEnter, } = props; return {r.title} }; const NavbarSearchItem_Post = props => { const { data: p, active, highlightIndex, onMouseEnter, } = props; return {p.title}
{p.title}
} class NavbarSearch extends React.Component { constructor(props) { super(props) this.state = { value: "", opened: false, nodes: [], highlighted: -1, preloading: false, used: false, }; this.loading = false; this.blurTimeout = undefined; this.searchTimeout = undefined; this.rowTypes = [ { type: "ranking", title: __navSearchLang.acZebricky, component: NavbarSearchItem_Post, }, { type: "review", title: __navSearchLang.acRecenze, component: NavbarSearchItem_Post, }, { type: "blogPost", title: __navSearchLang.acClanky, component: NavbarSearchItem_Post, }, { type: "product", title: __navSearchLang.acProdukty, component: NavbarSearchItem_Product, }, { type: "category", title: __navSearchLang.acKategorieProduktu, component: NavbarSearchItem_Generic, }, { type: "brand", title: __navSearchLang.acVyrobci, component: NavbarSearchItem_Generic, }, ]; this._open = this.open.bind(this); this._close = this.close.bind(this); this._toggleOpen = this.toggleOpen.bind(this); this._search = this.search.bind(this); this._onChange = this.onChange.bind(this); this._onBlur = this.onBlur.bind(this); this._onFocus = this.onFocus.bind(this); this._onMouseEnter = this.onMouseEnter.bind(this); this._onKeyDown = this.onKeyDown.bind(this); } componentDidUpdate(prevProps, prevState, snapshot) { if(!prevState.opened && this.state.opened) { const input = this.refs.input; input.focus() input.select() } } open() { this.setState({ opened: true, }) this.props.onToggle?.(true) } close() { this.setState({ opened: false, }) this.props.onToggle?.(false) } toggleOpen() { if(this.state.opened) { this.close() } else { this.open() } } async search() { if(this.loading) return; this.loading = true; const nextState = {}; try { const fd = new FormData(); fd.append("request", "index/search") fd.append("query", this.state.value) fd.append("all", "1") const r = await fetch(`${__httppath}/ajax/`, { method: "POST", body: fd, }); const e = await r.json(); if(e.status == "OK") { nextState.nodes = e.data.nodes; nextState.highlighted = -1; nextState.used = true; } else { console.error(e) } } catch(err) { console.error(err) } finally { nextState.preloading = false; this.setState(nextState) this.loading = false; } } onChange(ev) { const val = ev.currentTarget.value; const isSearchable = val.length >= 3; this.setState({ value: val, preloading: isSearchable, }, () => { if(isSearchable) { clearTimeout(this.searchTimeout) this.searchTimeout = setTimeout(this._search, 750); } }) } onBlur() { clearTimeout(this.blurTimeout) this.blurTimeout = setTimeout(this._close, 300); } onFocus() { clearTimeout(this.blurTimeout) } onMouseEnter(ev) { const hlindex = parseInt(ev.currentTarget.dataset.jsHlindex); this.setState({ highlighted: hlindex, }) } onKeyDown(ev) { switch(ev.key) { case "ArrowDown": { ev.preventDefault() const nodeCount = this.state.nodes.length; let next = this.state.highlighted + 1; if(next > nodeCount - 1) next = -1; this.setState({ highlighted: next, }) } break; case "ArrowUp": { ev.preventDefault() const nodeCount = this.state.nodes.length; let next = this.state.highlighted - 1; if(next < -1) next = nodeCount - 1; this.setState({ highlighted: next, }) } break; case "Enter": const hl = this.state.highlighted; if(hl > -1 && this.state.nodes[hl] !== undefined) { window.location.href = this.state.nodes[hl].link; } else { window.location.href = `${__httppath}/hledat/?q=${encodeURIComponent(this.state.value)}`; } break; case "Escape": this.refs.input.blur() break; } } render() { let hlIterator = -1; let results; const { nodes, highlighted, preloading, used, opened, value, } = this.state; if(used && opened) { const segments = []; for(const t of this.rowTypes) { const results = nodes.filter(e => e.type == t.type); if(results.length == 0) continue; segments.push(
{t.title}
{results.map(r => { hlIterator++; return React.createElement(t.component, { key: r.id, data: r, active: highlighted == hlIterator, highlightIndex: hlIterator, onMouseEnter: this._onMouseEnter, }) })}
) } results = (
{segments} {nodes.length > 0 ? __navSearchLang.acVsechnyVysledky : __navSearchLang.acZadneVysledky}
); } return
{preloading &&
} {results}
} } const onNavbarSearchToggle = opened => { if(opened) { $navbar.navbar.classList.add("search-active") } else { $navbar.navbar.classList.remove("search-active") } }; ReactDOM.render(, document.getElementById("navbar-search")) var siTriggers = document.querySelectorAll("[data-subitems-trigger]"); var siCloses = document.querySelectorAll("[data-subitems-close]"); for(var i=0; i { if(trigger.hasAttribute("href")) { trigger.addEventListener("click", (ev) => { if(window.innerWidth < 768) { ev.preventDefault() } }) } }) var trackedProducts = document.querySelectorAll("a[data-tr-product]"); for(var i=0; i
); } }); var $SHOWCOOKIECONFIRM = new Cookie("_ccf", "1"); if($SHOWCOOKIECONFIRM.value === "1") { ReactDOM.render(, document.getElementById("cookie-confirm")); } function get_window_width() { return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; } function get_window_height() { return window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; } var windowHeight, botherOptimizing, panelTop; var footerHeight = document.querySelector("footer.footer-main").offsetHeight; var sticky = document.getElementById("sticky-panel"); var panelTop = sticky.offsetTop; var prep = document.getElementById("sticky-prep"); var prepHeight; var TOPOFFSET = 90; var BOTTOMOFFSET = 30; var panelHeight = sticky.offsetHeight; var threshold = typeof __stickyDeviceThreshold != "undefined" ? __stickyDeviceThreshold : 1024; assignValues(); function assignValues() { setTimeout(function(){ prepHeight = prep.offsetHeight; windowHeight = get_window_height(); botherOptimizing = decideBother(); sticky.style.width = prep.offsetWidth+"px"; panelTop = sticky.offsetTop-TOPOFFSET; if(!botherOptimizing) { sticky.style.position = "static"; sticky.style.top = "auto"; sticky.style.bottom = "auto"; } }, 300); } function decideBother() { return get_window_width() >= threshold && body.offsetHeight > footerHeight+prep.offsetTop+prepHeight+panelHeight+BOTTOMOFFSET+200; } window.addEventListener("resize",function(){ assignValues(); optimizeSticky(); }); document.addEventListener("scroll",function(){ optimizeSticky(); }); function optimizeSticky() { if(botherOptimizing) { var scrollTop = getScrollTop(); if(scrollTop > panelTop) { var offset = body.offsetHeight-footerHeight-scrollTop-windowHeight-BOTTOMOFFSET; var maxHeight = windowHeight-TOPOFFSET+offset; if(maxHeight < panelHeight) { sticky.style.position = "fixed"; sticky.style.top = "auto"; sticky.style.bottom = (-offset)+"px"; } else { sticky.style.position = "fixed"; sticky.style.top = TOPOFFSET+"px"; sticky.style.bottom = "auto"; } } else { sticky.style.position = "static"; sticky.style.top = "auto"; sticky.style.bottom = "auto"; } } } var NewSlider = React.createClass({ getInitialState() { return { elementCount: 0, totalWidth: 0, page: 1, maxPages: 0 }; }, html: "", rowClass: "", touch: { active: false, initialX: null, reactionLimit: 80 }, setTransform(px) { return { WebkitTransform: "translateX("+px+"px)", MozTransform: "translateX("+px+"px)", msTransform: "translateX("+px+"px)", OTransform: "translateX("+px+"px)", transform: "translateX("+px+"px)" }; }, getDimensions() { const el = document.querySelector("#"+this.props.elementID+" .row div[class^='col-']") var elw = el === null ? 1 : el.offsetWidth - 3; var elc = document.querySelectorAll("#"+this.props.elementID+" .row div[class^='col-']").length; var ttw = ReactDOM.findDOMNode(this.refs.overhaul).offsetWidth; this.setState({ elementCount: elc, totalWidth: ttw, page: 1, maxPages: Math.ceil(elc*elw/ttw), showArrows: Math.round(ttw/elw) < elc }); }, componentWillMount() { this.html = document.querySelector("#"+this.props.elementID+" .row").innerHTML; this.rowClass = document.querySelector("#"+this.props.elementID+" .row").className; }, componentDidMount() { var self = this; window.addEventListener("resize", function(){ self.getDimensions(); }); this.getDimensions(); }, handleAction(type, data) { switch(type) { case "prev": var a = this.state.page == 1 ? this.state.maxPages : this.state.page-1; this.setState({ page: a }); this.handleAction("refreshBLazy"); break; case "next": var a = this.state.page == this.state.maxPages ? 1 : this.state.page+1; this.setState({ page: a }); this.handleAction("refreshBLazy"); break; case "touch-start": this.touch.active = true; this.touch.initialX = data.touches[0].pageX; break; case "touch-move": if(this.touch.active) { var diff = this.touch.initialX - data.touches[0].pageX; if(diff > this.touch.reactionLimit) { this.handleAction("next"); } else if(diff < -this.touch.reactionLimit) { this.handleAction("prev"); } if(Math.abs(diff) > this.touch.reactionLimit) { this.touch.active = false; } } break; case "touch-end": this.touch.active = false; break; case "refreshBLazy": if(typeof blazy != "undefined") { setTimeout(function(){ blazy.revalidate(); }, 350); } break; } }, render() { var arrows = []; if(this.state.showArrows) { arrows.push(
); arrows.push(
); } return (
{arrows}
); } }); var ecl = document.getElementById("eshop-category-list"); var ect = document.getElementById("eshop-category-toggle"); ect.addEventListener("click", function(){ toggleClass(ecl, "active"); toggleClass(ect, "active"); }); document.getElementById("brand-select")?.addEventListener("change", ev => { const value = ev.currentTarget.value; const append = value === "" ? "" : `${value}/`; const pathname = `/${__eeshop.page}/${__eeshop.c.seo}/${append}${window.location.search}`; window.location.href = pathname; }) document.getElementById("order-select")?.addEventListener("change", ev => { const pathname = `${window.location.pathname}?seradit=${ev.currentTarget.value}`; window.location.href = pathname; }) var ns1 = document.getElementById("new-slider"), ns2 = document.getElementById("new-slider-2"); if(ns1) ReactDOM.render(, ns1); if(ns2) ReactDOM.render(, ns2); var blazy = new Blazy({ selector: ".card.g-h .img", offset: 500, }); var ViewCookie = new Cookie("_fw_view", "list"); var ViewToggle = React.createClass({ getInitialState() { return { view: ViewCookie.value }; }, handleAction(type, data) { switch(type) { case "change-view": if(this.state.view == data) return; this.setState({ view: data }); break; case "use-transponation": var row = document.querySelector(".row.product-cards"); var cols = row.querySelectorAll("[class^='col-']"); var cards = row.querySelectorAll(".card.g-h"); addClass(row, "transponed"); for(var i=0; i
) } }); var vt = document.getElementById("view-toggle"); if(vt) ReactDOM.render(, vt);