(function () { var Skubacz = { configuration: {} }, disableTouch = false, isIframeScrollingEnabled = false, lastScrollY = 0; /** * Get the current computed width (optionally outer width including padding, border and margin). * * @param element {HTMLElement} * @param outerWidth {boolean} * @returns {number} */ function getWidth(element, outerWidth) { outerWidth = outerWidth || false; var elementWidth = element.offsetWidth; if (outerWidth) { elementWidth += parseInt(window.getComputedStyle(element).marginLeft) + parseInt(window.getComputedStyle(element).marginRight); } return parseInt(elementWidth); } /** * Get the current computed height (optionally outer height including padding, border and margin). * * @param element {HTMLElement} * @param outerHeight {boolean} * @returns {number} */ function getHeight(element, outerHeight) { outerHeight = outerHeight || false; var elementHeight = element.offsetHeight; if (outerHeight) { elementHeight += parseInt(window.getComputedStyle(element).marginTop) + parseInt(window.getComputedStyle(element).marginBottom); } return parseInt(elementHeight); } /** * Cross-browser window width and height. * * @returns {number[]} */ function getWindowSize() { var width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; var height = window.innerHeight|| document.documentElement.clientHeight|| document.body.clientHeight; return [width, height]; } function getScrollY() { var y = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop || 0; return y; } function setScrollY(y) { window.scrollTo(0, y); } function setHeight(elem, h) { elem.style.height = h + "px"; } window.addEventListener("touchmove", function(e) { if (isExtraSmall() === true && disableTouch === true) { e.preventDefault(); } }); function isExtraSmall() { return window.matchMedia('(max-width: 767px)').matches } function getIframe() { return document.getElementById('skubacz_menu_widget'); } function getIframeWrapper() { return document.getElementById('restaumatic_menu_widget_wrapper'); } function getOffsetTop(element) { var offsetTop = element.offsetTop; if (typeof element.offsetParent !== 'undefined' && element.offsetParent !== null) { offsetTop += getOffsetTop(element.offsetParent); } return offsetTop; } /** * Toggle iframe placeholder which keeps the place for iframe in fullscreen mode (avoids parent content movement in fullscreen mode). * * @param mode {string} enable or disable */ function toggleIframePlaceholder(mode) { var iframePlaceholder = document.getElementById("restaumatic_menu_widget_wrapper"); if (!iframePlaceholder) { return; } if (mode === 'disable') { iframePlaceholder.style.height = ""; } else if (mode === 'enable') { iframePlaceholder.style.height = getHeight(getIframe(), true) + "px"; } } /** * Set iframe size and position based on original values to simulate regular modal. * * @param mode */ function toggleIframeFullscreenDimentions(mode) { var iframe = getIframe(); if (mode === "disable") { // Restore original iframe size and position iframe.style.width = "100%"; iframe.style.left = ""; } else if (mode === "enable") { var iframeWrapper = getIframeWrapper(); var iframeWidth = getWidth(iframeWrapper); var iframeLeft = parseInt(iframeWrapper.getBoundingClientRect().left + document.body.scrollLeft); var windowWidth = getWindowSize()[0] iframe.style.width = iframeWidth + "px"; iframe.style.left = ((windowWidth - (iframeWidth + iframeLeft)) >= 0) ? iframeLeft + "px" : windowWidth - iframeWidth + "px"; // basic support for pages with horizontal scroll } } /** * Enable or disable fullscreen for iframe with Active Menu. * * @param mode {string} enable or disable */ function toggleIframeFullscreen(mode) { var iframe = getIframe(); if (mode === 'disable') { disableTouch = false; setScrollY(lastScrollY); toggleParentBackdrop(mode); toggleIframePlaceholder(mode); toggleIframeFullscreenDimentions(mode); iframe.classList.remove('restaumatic-iframe-fullscreen'); document.body.classList.remove('restaumatic-modal-open'); iframe.contentWindow.postMessage({type: 'DISABLE_FULLSCREEN_OFFSET'}, "*"); } else if (mode === 'enable') { var iframeOffsetTop = iframe.getBoundingClientRect().top; lastScrollY = getScrollY(); disableTouch = true; iframe.contentWindow.postMessage({ type: 'SET_FULLSCREEN_OFFSET', iframeOffsetTop: iframeOffsetTop, iframeFixedOffsetTop: getFixedOffsetTop() }, "*"); toggleIframeFullscreenDimentions(mode); toggleIframePlaceholder(mode); toggleParentBackdrop(mode); document.body.classList.add('restaumatic-modal-open'); iframe.classList.add('restaumatic-iframe-fullscreen'); } } /** * Enable or disable backdrop which simulates original modal behavior and catches clicks. * * @param mode {string} enable or disable */ function toggleParentBackdrop(mode) { mode = mode || 'disable'; var backdrop = document.getElementById("restaumatic_menu_widget_backdrop"); if (mode === 'disable' && !!backdrop) { backdrop.style.display = "none"; } else if (mode === 'enable') { if (!backdrop) { var iframeWrapper = getIframeWrapper(); backdrop = document.createElement("div"); backdrop.onclick = function (e) {}; // required to fire handleParentClick() because of the event bubbling on iOS backdrop.id = "restaumatic_menu_widget_backdrop"; backdrop.style.position = "fixed"; backdrop.style.top = "0"; backdrop.style.right = "0"; backdrop.style.bottom = "0"; backdrop.style.left = "0"; backdrop.style.backgroundColor = "#000" || "black"; backdrop.style.opacity = "0.5"; // has to be the same as defined is active_menu.scss (or variable default) backdrop.style.zIndex = "99998"; iframeWrapper.appendChild(backdrop); } else { backdrop.style.display = "block"; } } } /** * Fix stacking context issues with fixed positioned iframe within transformed parent. * * https://www.w3.org/TR/css-transforms-1/#transform-rendering * * @param mode {string} Possible values: `enable` or `disable` * @param applyForAllParents {boolean} (optional) Use `false` if you want to try detect and apply fix only for required elements. */ function toggleStackingContextFix(mode, applyForAllParents) { mode = mode || 'disable'; applyForAllParents = applyForAllParents || true; if (mode === 'disable') { var elements = document.querySelectorAll('.restaumatic-disable-stacking-context'); function removeClass(elements, className) { elements = elements || document.querySelectorAll(className); // Check for sequential modals. if (document.body.classList.contains('restaumatic-modal-open') || !elements) { return; } for (var i = 0; i < elements.length; ++i) { elements[i].classList.remove(className); } } removeClass(elements, 'restaumatic-disable-stacking-context'); // We need some delay to avoid animation on transformed elements. setTimeout(function () { removeClass(elements, 'restaumatic-disable-transition'); }, 100); } else { var iframe = getIframe(); var el; if (!iframe) { return; } /** * Check if stacking context is formed by provided element. * * https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context * https://github.com/w3c/csswg-drafts/issues/400 * * @param el */ function isStackingContextElement(el) { var i = 0; var stackingContextProps = ['transform', 'perspective', 'clip-path', 'isolation', 'will-change', 'filter', 'mask']; stackingContextProps = stackingContextProps.concat(['-webkit-transform', '-webkit-perspective', '-webkit-clip-path', '-webkit-filter', '-webkit-mask']); // prefixed values according to caniuse.com var computedStyle = window.getComputedStyle(el); var result = false; var hasChangingContextValue = false; for (; i < stackingContextProps.length; i++) { var prop = stackingContextProps[i]; var value = el.style[prop] || computedStyle[prop]; var regexp = new RegExp(/^$|^none$|^auto$/i); // allowed values which don't create new stacking context hasChangingContextValue = (typeof value === 'string') ? !regexp.test(value) : false; if (hasChangingContextValue) { result = true; break; } } return result; } // Enable fix for parent elements. for (el = iframe.parentNode; el && el !== document; el = el.parentNode) { if (applyForAllParents || isStackingContextElement(el)) { el.classList.add('restaumatic-disable-stacking-context'); el.classList.add('restaumatic-disable-transition'); } } } } /** * Fix layout displacement bug on iOS with sequential modals and iframe in fullscreen mode. * * To fix this we need to trigger layout "repaint" which magically adjusts wrong placement of the iframe content. */ function applyFullscreenLayoutFix(iframe) { iframe.style.boxShadow = "0 0 0 transparent"; setTimeout(function () { // This will trigger layout repaint. iframe.style.boxShadow = ""; }, 100) } /** * Ensure correct modal offset (fullscreen modal fix). */ function setFullscreenModalOffset(iframe) { iframe.contentWindow.postMessage({ type: 'SET_FULLSCREEN_MODAL_OFFSET', iframeFixedOffsetTop: getFixedOffsetTop() }, "*"); } /** * Check if selector is valid. * * @param selector * @returns {boolean} */ function isValidSelector(selector) { if (!selector || typeof(selector) !== "string") { return false; } try { document.querySelector(selector); } catch (e) { return false; } return true; } /** * Better resize event (debounced resize). * * @param callback * @param timeout * @returns {*} */ function onResizeEvent(callback, timeout) { window.onresize = function () { clearTimeout(timeout); timeout = setTimeout(callback, 100) }; return callback; } onResizeEvent(function () { var iframe = getIframe(); if (iframe && iframe.classList.contains("restaumatic-iframe-fullscreen")) { toggleIframeFullscreenDimentions('enable'); } }); function getElementsByCss(css) { var elements = document.getElementsByTagName('*'), result = [], i = 0, length = elements.length, elementStyle, addCurrent, prop; for (i = 0; i < length; i += 1) { elementStyle = elements[i].currentStyle || getComputedStyle(elements[i]); addCurrent = true; for (prop in css) { if (prop === 'width' && parseInt(css[prop]) === elements[i].offsetWidth) { addCurrent = true; break; } else if (isNaN(parseInt(elementStyle[prop])) || isNaN(parseInt(css[prop]))) { if (elementStyle[prop] !== css[prop]) { addCurrent = false; break; } } else { if (parseInt(elementStyle[prop]) !== parseInt(css[prop])) { addCurrent = false; break; } } } if (addCurrent) { result.push(elements[i]); } } return result; } function getFixedOffsetTop() { var useManualOffset = parseInt(Skubacz.configuration.manual_offset) === 1 && isValidSelector(Skubacz.configuration.offset_elements) ? true : false, elements = useManualOffset ? document.querySelectorAll(Skubacz.configuration.offset_elements) : getElementsByCss({position: 'fixed', top: 0, width: document.documentElement.clientWidth}), filteredElements = [].filter.call(elements, function(el) { return el.offsetHeight < document.documentElement.clientHeight }); return [].reduce.call(filteredElements, function(sum, el) { return sum + el.offsetHeight; }, 0); } function notifyScrollPosition(e) { var iframe = getIframe(); if (iframe && iframe.contentWindow) { var message = { type: 'PARENT_SCROLL', iframeParentIsExtraSmall: isExtraSmall(), iframeParentHeight: window.innerHeight, iframeOffsetTop: iframe.getBoundingClientRect().top, iframeOffsetBottom: iframe.getBoundingClientRect().bottom } iframe.contentWindow.postMessage(message, "*"); } } function handleParentClick(e) { var iframe = getIframe(); if (iframe && iframe.contentWindow) { if (e.target.id === "restaumatic_menu_widget_backdrop") { iframe.contentWindow.postMessage({type: 'HIDE_MODAL'}, "*"); } } } /** * Disable custom scrollbars that are causing AM scrolling issues. * * Disables: * - niceScroll */ function disableCustomScrollbar() { if (typeof jQuery === "function" && typeof jQuery("html").getNiceScroll === "function" && typeof jQuery("html").getNiceScroll().remove === "function") { jQuery("html, body").getNiceScroll().remove(); jQuery("body").removeClass("nice-scroll"); trackEvent('custom_scroll_disabled', {parentUrl: window.location.href}); } } /** * Check if original AM embed code (iframe) has the correct `src` attribute. * * @param iframeOriginalSrc {string} `src` attribute of the original AM embed code (iframe). */ function isCorrectIframeSrc(iframeOriginalSrc) { iframeOriginalSrc = iframeOriginalSrc || ""; return iframeOriginalSrc.indexOf("https://veloce-e-gusto.skubacz.pl/") !== -1; } /** * Check if position fixed works correctly. * * Detect changed stacking context by `transform` property on some parent element which makes fixed elements act like `position: absolute`. * * @param element {HTMLElement} Element with `position: fixed` and explicitly declared `top` and `left` properties. * @returns {boolean} */ function isCorrectFixedPosition(element) { var top = element.style.top || 0; var left = element.style.left || 0; return element.getBoundingClientRect().top === parseInt(top) && element.getBoundingClientRect().left === parseInt(left); } /** * Init "dynamic iframe" which stands for iframe with dynamically adjusted iframe height based on current iframe content height. */ function initDynamicIframe() { var iframe = getIframe(); if (iframe && iframe.contentWindow) { iframe.contentWindow.postMessage({type: 'INIT_DYNAMIC_IFRAME'}, "*"); } } /** * Track event. * * @param name {string} Event name. * @param params {object} Object containing params for tracking function. */ function trackEvent(name, params) { var iframe = getIframe(); iframe.contentWindow.postMessage({ type: 'TRACK_EVENT', name: name, params: params }, "*"); } function initAnalytics() { getAnalyticsClientId(function (clientId) { var iframe = getIframe(); iframe.contentWindow.postMessage({ type: 'INIT_ANALYTICS', clientId: clientId }, "*") }); } function getAnalyticsClientId( callback ) { if (window._gaq || window._gat) { console.log("Legacy analytics detected, crossdomain tracking disabled") callback(null) } else if (window.dataLayer && typeof window.gtag === 'function') { console.log("gtag.js detected, setting up crossdomain tracking") // No clean way to retrieve tracker id, so we retrieve it from the first // gtag('config', 'mId') command, which creates ['config', 'measurementId', { .. }] data layer entry const measurmentId = window.dataLayer.find((c) => c[0] === 'config')[1] gtag('get', measurmentId, 'client_id', function (clientId) { callback(clientId) }); } else if (window.GoogleAnalyticsObject && typeof window.ga === "function") { console.log("analytics.js detected, setting up crossdomain tracking") ga(function (tracker) { var t = ga.getByName("restaumatic") || tracker || ga.getAll()[0] callback(t.get('clientId')) }) } else { console.log("No analytics detected, crossdomain tracking disabled") callback(null) } } function onMessage(e) { var iframe = getIframe(), offsetTop = 0, h = 0; switch(e.data.type) { case 'CONFIG': Skubacz.configuration.manual_offset = e.data.manual_offset; Skubacz.configuration.offset_elements = e.data.offset_elements; break; case 'SIZE_STRETCH': if (e.data.applyLayoutFix === true) { applyFullscreenLayoutFix(iframe); if (e.data.fullscreenModalFix === true) { setFullscreenModalOffset(iframe); } } else { toggleIframeFullscreen('enable'); if (!isCorrectFixedPosition(iframe)) { toggleStackingContextFix('enable'); } } break; case 'SIZE_DEFAULT': toggleIframeFullscreen('disable'); toggleStackingContextFix('disable'); break; case 'SCROLL_TO_IFRAME': offsetTop = getOffsetTop(iframe) - getFixedOffsetTop() + e.data.extraOffsetTop; setScrollY(offsetTop); break; case 'HISTORY_PUSH': var path = e.data.path, menuPath = "/restauracja/veloce-e-gusto", search = '', url = ''; if (typeof path !== 'undefined' && path !== null && path.length > 0) { if (menuPath !== path) { search = setParameter(window.location.search, '_am_', encodeURIComponent(path)); } else { search = removeParameter(window.location.search, '_am_'); } url = window.location.pathname + search + window.location.hash; window.history.replaceState(null, null, url); } break; default: h = parseInt(e.data.height); if (!isIframeScrollingEnabled && !isNaN(h)) { setHeight(iframe, h); if (e.data.scrollTop) { scroll(0, 0); } } notifyScrollPosition(); break; } } function onParentLoad() { disableCustomScrollbar(); } function initParent() { window.addEventListener('message', onMessage, false); window.addEventListener('scroll', notifyScrollPosition, false); window.addEventListener('resize', notifyScrollPosition, false); window.addEventListener('click', handleParentClick, false); window.addEventListener("load", onParentLoad, false); if (window.MutationObserver) { var config = { attributes: false, childList: true, characterData: true, subtree: true}; var observer = new MutationObserver(function (mutations, obs) { var iframe = getIframe(); if (!iframe) { console.log("Unsubscribing AM events"); window.removeEventListener('message', onMessage, false); window.removeEventListener('scroll', notifyScrollPosition, false); window.removeEventListener('resize', notifyScrollPosition, false); window.removeEventListener('click', handleParentClick, false); window.removeEventListener("load", onParentLoad, false); obs.disconnect(); } }); observer.observe(document.body, config); } } function setCookie(cname, cvalue, exdays) { var d = new Date(); d.setTime(d.getTime() + (exdays*24*60*60*1000)); var expires = "expires="+d.toUTCString(); document.cookie = cname + "=" + cvalue + "; " + expires; } function getCookie(cname) { var name = cname + "="; var ca = document.cookie.split(';'); for(var i=0; i 0) { resultUrl += '?' + urlParams; } return resultUrl; } function getParameterByName(name) { var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search); return match && decodeURIComponent(match[1].replace(/\+/g, ' ')); } function removeElement(selector) { var element = document.querySelector(selector); if (element && element.parentNode) { element.parentNode.removeChild(element); } } function insertAfter(selector, node) { var element = document.querySelector(selector); element.parentNode.appendChild(node); } function getIframeUrl() { var root = "https://veloce-e-gusto.skubacz.pl/", menuPath = "/restauracja/veloce-e-gusto", paramUrl = getParameterByName('_am_'), url = ''; menuPath = paramUrl ? decodeURI(paramUrl) : menuPath; url = root + menuPath.replace(/^\//, ''); return url; } function getCanonical() { var links = document.getElementsByTagName("link"), canonical = null; for (var i = 0; i < links.length; i ++) { if (links[i].getAttribute("rel") === "canonical") { canonical = links[i].getAttribute("href"); break; } } return canonical; } function setCanonical(url) { var link = document.createElement("link"); link.setAttribute('rel', 'canonical'); link.setAttribute('href', url); document.head.appendChild(link); } function main() { var isIframeEmbed = !!document.getElementById("restaumatic_menu_widget_wrapper") && !document.querySelector("a.skubacz_widget"); var iframeWrapper = isIframeEmbed ? document.getElementById("restaumatic_menu_widget_wrapper") : document.createElement("div"); var iframe = isIframeEmbed ? iframeWrapper.querySelector("iframe") : document.createElement("iframe"); var iframeOriginalSrc = iframe.src; if (isIframeEmbed) { // We can receive a different url here via _am_ param var newUrl = getIframeUrl(); if (newUrl != iframe.src) { iframe.src = newUrl; } } else { iframeWrapper.id = "restaumatic_menu_widget_wrapper"; iframe.src = getIframeUrl(); } iframe.scrolling = isIframeScrollingEnabled ? "yes" : "no"; iframe.frameborder = "0"; iframe.allowTransparency = "true"; iframe.id = "skubacz_menu_widget"; iframe.allow="geolocation"; iframe.style.border = "none"; iframe.style.overflow = "hidden"; iframe.style.margin = "10px 0px"; iframe.style.maxWidth = "100%"; iframe.style.width = "100%"; iframe.style.display = "block"; iframe.style.minHeight = isIframeScrollingEnabled ? Math.max(getWindowSize()[1], 500) + 'px' : '500px'; function onIframeLoad() { if (isIframeEmbed) { if (!isCorrectIframeSrc(iframeOriginalSrc)) { trackEvent('incorrect_am_iframe_src', {iframeSrc: iframeOriginalSrc}); } } else { removeElement("a.skubacz_widget"); } notifyScrollPosition(); initAnalytics(); if (!isIframeScrollingEnabled) { initDynamicIframe(); } } if (iframe.attachEvent) { iframe.attachEvent("onload", onIframeLoad); } else { iframe.onload = onIframeLoad; } if (!isIframeEmbed) { insertAfter("a.skubacz_widget", iframeWrapper); iframeWrapper.appendChild(iframe); } initParent(); var canonical = getCanonical(); if (typeof canonical === 'undefined' || canonical === null) { setCanonical(removeParameter(window.location.href, '_am_')); } var style = document.createElement("style"); style.appendChild(document.createTextNode("")); //webkit hack document.head.appendChild(style); // style.setAttribute("media", "screen and (max-width : 767px)"); style.sheet.insertRule("#restaumatic_menu_widget_wrapper { position: relative !important; width: 100% !important; width: 100% !important; max-width: 100% !important; margin: 0 !important; padding: 0 !important; border: 0 !important; }", 0); style.sheet.insertRule(".restaumatic-modal-open { overflow: hidden !important; }", 0); style.sheet.insertRule("#skubacz_menu_widget { width: 100%; }", 0); // fix for some rare cases when parent site removes the iframe width from inline styles // Fix transform stacking context change and fixed iframe issues related to it style.sheet.insertRule(".restaumatic-disable-stacking-context { -o-transform: none !important; -moz-transform: none !important; -ms-transform: none !important; -webkit-transform: none !important; transform: none !important; -webkit-perspective: none !important; perspective: none !important; clip-path: none !important; isolation: auto !important; will-change: auto !important; -webkit-filter: none !important; filter: none !important; -webkit-mask: none !important; mask: none !important; }", 0); style.sheet.insertRule(".restaumatic-disable-transition { -webkit-transition-duration: 0s !important; -moz-transition-duration: 0s !important; -ms-transition-duration: 0s !important; -o-transition-duration: 0s !important; transition-duration: 0s !important; }", 0); style.sheet.insertRule(".restaumatic-iframe-fullscreen { background: none !important; position: fixed !important; min-height: 100% !important; max-height: 100% !important; top: 0 !important; bottom: 0 !important; margin-top: 0 !important; margin-bottom: 0 !important; z-index: 9999999 !important; }", 0); // min-height/max-height - mobile safari iframe height fix } if (document.querySelector('a.skubacz_widget') || document.getElementById("restaumatic_menu_widget_wrapper")) { main(); } else { document.addEventListener("DOMContentLoaded", main); } })();