vinoShipperInjector = (function (window) { var cartInitialized = false; var cartIdInitialized = false; var module = {}; var googleAttempts = 0; var config = { sidePanelId: 'vs-cart', iframeId: 'vs-iframe', disableResize: window.vsDisableResize ? window.vsDisableResize : false, server: detectServer(), clientCss: detectClientCSSOverride(), injectorCss: detectServer() + '/static/css/iframe/v2/injector.css', defaultIFramePadding: 100, defaultClubSignUpCallback: function () { vsLog('Club Sign Up Complete'); } }; var SIDE_PANEL = '
'; var CART_BUTTON = '
{items}
'; // Utility Functions var vsLog = window.vsLog = function () { vsLog.history = vsLog.history || []; vsLog.history.push(arguments); if (this.console) { console.log(Array.prototype.slice.call(arguments)) } }; var onDocumentReady = (function () { var f, b, c = {}; c["[object Boolean]"] = "boolean"; c["[object Number]"] = "number"; c["[object String]"] = "string"; c["[object Function]"] = "function"; c["[object Array]"] = "array"; c["[object Date]"] = "date"; c["[object RegExp]"] = "regexp"; c["[object Object]"] = "object"; var d = { isReady: false, readyWait: 1, holdReady: function (g) { if (g) { d.readyWait++ } else { d.ready(true) } }, ready: function (g) { if ((g === true && !--d.readyWait) || (g !== true && !d.isReady)) { if (!document.body) { return setTimeout(d.ready, 1) } d.isReady = true; if (g !== true && --d.readyWait > 0) { return } f.resolveWith(document, [d]) } }, bindReady: function () { if (f) { return } f = d._Deferred(); if (document.readyState === "complete") { return setTimeout(d.ready, 1) } if (document.addEventListener) { document.addEventListener("DOMContentLoaded", b, false); window.addEventListener("load", d.ready, false) } else { if (document.attachEvent) { document.attachEvent("onreadystatechange", b); window.attachEvent("onload", d.ready); var g = false; try { g = window.frameElement == null } catch (h) { } if (document.documentElement.doScroll && g) { a() } } } }, _Deferred: function () { var j = [], k, h, i, g = { done: function () { if (!i) { var m = arguments, n, q, p, o, l; if (k) { l = k; k = 0 } for (n = 0, q = m.length; n < q; n++) { p = m[n]; o = d.type(p); if (o === "array") { g.done.apply(g, p) } else { if (o === "function") { j.push(p) } } } if (l) { g.resolveWith(l[0], l[1]) } } return this }, resolveWith: function (m, l) { if (!i && !k && !h) { l = l || []; h = 1; try { while (j[0]) { j.shift().apply(m, l) } } catch (n) { } finally { k = [m, l]; h = 0 } } return this }, resolve: function () { g.resolveWith(this, arguments); return this }, isResolved: function () { return !!(h || k) }, cancel: function () { i = 1; j = []; return this } }; return g }, type: function (g) { return g == null ? String(g) : c[Object.prototype.toString.call(g)] || "object" } }; function a() { if (d.isReady) { return } try { document.documentElement.doScroll("left") } catch (g) { setTimeout(a, 1); return } d.ready() } if (document.addEventListener) { b = function () { document.removeEventListener("DOMContentLoaded", b, false); d.ready() } } else { if (document.attachEvent) { b = function () { if (document.readyState === "complete") { document.detachEvent("onreadystatechange", b); d.ready() } } } } function e(h) { d.bindReady(); var g = d.type(h); f.done(h) } return e })(); var whichAnimationEvent = function () { var t, el = document.createElement("fakeelement"); var animations = { "animation": "animationend", "OAnimation": "oAnimationEnd", "MozAnimation": "animationend", "WebkitAnimation": "webkitAnimationEnd" }; for (t in animations) { if (el.style[t] !== undefined) { return animations[t]; } } }; var detectAnimationSupport = function (id) { var animation = false, animationstring = 'animation', keyframeprefix = '', domPrefixes = 'Webkit Moz O ms Khtml'.split(' '), pfx = '', elm = document.getElementById(id); if (elm.style.animationName !== undefined) { animation = true; } if (animation === false) { for (var i = 0; i < domPrefixes.length; i++) { if (elm.style[domPrefixes[i] + 'AnimationName'] !== undefined) { pfx = domPrefixes[i]; animationstring = pfx + 'Animation'; keyframeprefix = '-' + pfx.toLowerCase() + '-'; animation = true; break; } } } return animation; }; var supplant = function (input, model) { vsLog(input); vsLog(model); if (!input || !model) { return input; } return input.replace(/{([^{}]*)}/g, function (a, b) { var r = model[b]; return typeof r === 'string' || typeof r === 'number' ? r : a; }); }; var qsParam = function (name) { name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]"); var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"), results = regex.exec(location.search); return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); }; var isBlocker = function (callback) { var msie = window.navigator.userAgent.indexOf("MSIE "); if (msie > -1 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) return; var testURL = 'https://www.google-analytics.com/analytics.js' var myInit = { method: 'HEAD', mode: 'no-cors' }; var myRequest = new Request(testURL, myInit); fetch(myRequest).then(function (response) { return response; }).then(function (response) { callback && callback(false) }).catch(function (e) { callback && callback(true) }); } // Detect Configuration, for CI builds we want to use the same hostname as the parent frame, // everywhere else we want to use the specific url for our environment. IE: vinoshipper.com or staging.aws.zlminc.com function detectServer() { var server = 'https://vinoshipper.com'; if (window.location.hostname && window.location.hostname.indexOf('aws.zlminc.com') > 0 && window.location.hostname.indexOf('catalog.aws.zlminc.com') < 0) { server = '//' + window.location.hostname; } return server; } function detectClientCSSOverride() { return window.vsCssUrl || window.vinoshipperCss || ""; } //Page Manipulation Functions function injectCss(href) { // bail out if already injected var styles = document.styleSheets; for (var i = 0, max = styles.length; i < max; i++) { if (styles[i].href === href) return; } var head = document.getElementsByTagName('head')[0]; var style = document.createElement('link'); style.type = 'text/css'; style.rel = 'stylesheet'; style.href = href; head.insertBefore(style, head.firstChild); } function injectHtml(html, containerId) { var container = containerId ? document.getElementById(containerId) : document.getElementsByTagName('body')[0]; container.insertAdjacentHTML('beforeend', html); var x = document.getElementsByClassName("vs-loading-msg"); for (var i = 0; i < x.length; i++) { x[i].style.display = "none"; } } function appendHtmlInto(target, content, data) { clearHtml(target); var interpolated = supplant(content, data); var receiverDiv = document.getElementById(target); receiverDiv.insertAdjacentHTML('beforeend', interpolated); } function clearHtml() { var div = document.getElementById('vs-injected-div'); if (div) { div.parentNode.removeChild(div); } } function injectFragmentFromServer(path, container) { var xhr = new XMLHttpRequest(); xhr.timeout = 2000; xhr.onreadystatechange = function() { if (xhr.readyState === 4) { if (xhr.status >= 200 && xhr.status < 300) { container.innerHTML = xhr.responseText; } else if (xhr.status == 404) { container.appendChild(document.createComment("Winery ID / Product ID combination not found")); } else { console.log('Not ready'); } } } xhr.ontimeout = function () { console.log('Timeout'); } xhr.open("GET", config.server + path); xhr.send(); } function resizeContentIframe(height) { var body = document.body, html = document.documentElement; //hack: need fixed height to deal with mobile safari iframe in a fixed div issues var width = Math.max(body.scrollWidth, body.offsetWidth, html.clientWidth, html.scrollWidth, html.offsetWidth); if (width > 480) return; if (!height) { height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight); } document.getElementById('vs-iframe-wrapper').style.height = height + 'px'; } //HTML Generation Functions function contentIframeHTML(title, page, cssFile, angularPath, params) { module.onClubSignupComplete = params.callback || config.defaultClubSignUpCallback; module.padding = isNaN(params.padding) ? config.defaultIFramePadding : params.padding; var scrolling = config.disableResize ? '' : 'scrolling="no"'; var angular = angularPath ? '#' + angularPath + '?' : '&'; var tkit = window.tkit ? 'tkit=' + window.tkit + "&" : ''; var galinker = module.gaLinker ? module.gaLinker + '&' : ''; var gacid = module.gaClientId ? 'gacid='+module.gaClientId + '&' : ''; var preorder = params.preorder ? 'preorder=true' + '&' : ''; var clubIdLock = window.vsClubIdLock ? 'clubidlock=true' + '&' : ''; var clubAllowList = window.vsClubAllowList ? 'cluballowlist=' + window.vsClubAllowList.join(',') + '&' : ''; var cart = module.sessionid ? 'cartId=' + module.sessionid + '&' : ''; return '
'; } function cartIFrameHTML() { var cartId = ""; if (module.sessionid) { cartId = "cartId=" + module.sessionid + "&"; } var wineryId = ''; if(window.vsWineryId) { wineryId = "wineryId=" + window.vsWineryId + "&"; } var returnUrl = window.vsReturnUrl || window.location.href; var galinker = module.gaLinker ? module.gaLinker + '&' : ''; var gacid = module.gaClientId ? 'gacid='+module.gaClientId + '&' : ''; return '
'; } //Interact with the cart function initCart() { if ((typeof window.vsShowCart !== undefined) && window.vsShowCart === false) return; injectHtml(SIDE_PANEL); destroyCart(); cartInitialized = true; } //Initialize cart sessionid function initCartId() { var cartId = ""; if (module.sessionid) { cartId = "cartId=" + module.sessionid + "&"; } var wineryId = ''; if(window.vsWineryId) { wineryId = "wineryId=" + window.vsWineryId + "&"; } cartSessionIframe = ''; injectHtml(cartSessionIframe); cartIdInitialized = true; } function cartContents(cartId, cb) { var contents = { items: 0 }; if (!cartId) { cartQty = contents; return; } var xhr = new XMLHttpRequest(); xhr.timeout = 2000; xhr.onreadystatechange = function() { if (xhr.readyState === 4) { if (xhr.status >= 200 && xhr.status < 300) { var cart = JSON.parse(xhr.responseText); var totalQty = 0; cart.contents.forEach(function(lineItem) { totalQty += lineItem.qty; }) cb({ items: totalQty }); } else { console.log('Not ready'); } } } xhr.ontimeout = function () { console.log('Timeout'); } xhr.open("GET", config.server + '/json-api/v2/cart/' + cartId); xhr.send(); } function addItemToCart(productId, quantity, landingPage) { var xhr = new XMLHttpRequest(); xhr.open("POST", config.server + '/iframe/v2/cart/add?cartId=' + module.sessionid); xhr.onload = showCart; xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhr.send("id=" + productId + "&quantity=" + quantity + "&landingPage=" + landingPage); } function destroyCart() { cartQty = { items: '' }; appendHtmlInto(config.sidePanelId, CART_BUTTON, cartQty); cartContents(module.sessionid, function(qty){ appendHtmlInto(config.sidePanelId, CART_BUTTON, qty); document.getElementsByTagName("body")[0].style.overflow = 'visible'; document.getElementById('vs-injected-div').onclick = showCart; }); } function hideCart() { if (detectAnimationSupport(config.sidePanelId)) { var elm = document.getElementById('vs-injected-div'); var transitionEvent = whichAnimationEvent(); var onAnimationEnd = function (event) { elm.removeEventListener(transitionEvent, onAnimationEnd); destroyCart(); }; elm.addEventListener(transitionEvent, onAnimationEnd); elm.className = 'vs-cart-open vs-closing'; } else { destroyCart(); } } function showCart() { appendHtmlInto(config.sidePanelId, cartIFrameHTML()); document.getElementsByTagName("body")[0].style.overflow = 'hidden'; document.getElementById('vs-injected-div').onclick = hideCart; document.getElementById('vs-iframe-stage').focus(); } //Communicate with the IFrame function onMessage(message) { vsLog(message); if (typeof message.data !== "string") return; if (message.data === 'canHazPostMessage') { document.getElementById(config.iframeId).contentWindow.postMessage('canHazPostMessage ack', "*"); } else if (message.data.indexOf('canHazPostMessage:') >= 0) { module.sessionid = message.data.split(':')[1]; window.parent.document.dispatchEvent(new CustomEvent('vsCartIdEvent', { detail: module.sessionid })); if (document.getElementById('vs-cart-count')) { cartContents(module.sessionid, function(qty) { document.getElementById('vs-cart-count').innerText = qty.items; }); } if (document.getElementById('vs-iframe')) { document.getElementById(config.iframeId).contentWindow.postMessage('canHazPostMessage ack', "*"); } } else if (message.data.indexOf('displayCart:') >= 0) { module.sessionid = message.data.split(':')[1]; showCart(); } else if (message.data === 'hideCart') { hideCart(); } else if (message.data.indexOf('iframe-height:') >= 0) { var height = message.data.split(':')[1]; if (!config.disableResize) { height = parseInt(height) + module.padding; if (document.getElementById('vs-iframe')) { document.getElementById('vs-iframe').parentNode.style.height = height + 'px'; } } } else if (message.data.indexOf('height:') >= 0) { resizeContentIframe(message.data.split(':')[1]); } else if (message.data.indexOf('clubSignUpComplete') >= 0) { var payload = message.data.split(':')[1]; module.onClubSignupComplete(payload); } } function initGoogle(callback) { attempts = googleAttempts || 0; if (!isBlocker() && window.ga && ga.create && !window.vsSkipAnalytics) { ga(function () { if (ga.getAll && ga.getAll().length > 0) { var tracker = ga.getAll()[0]; module.gaClientId = tracker.get('clientId'); module.gaLinker = tracker.get('linkerParam'); } googleAttempts = attempts + 1; callback(); }); } else { if (attempts <= 3) { //retry in case GA is just slow setTimeout(function () { vsLog("attempt to load google: " + attempts + " skip:" + window.vsSkipAnalytics); googleAttempts = attempts + 1; initGoogle(callback); }, 100); } else { vsLog('Google Analytics is blocked'); googleAttempts = attempts + 1; callback(); } } googleAttempts = attempts + 1; } // add parameters you need here var onReady = function (callback) { callback = callback || function () { }; // wait until DOM is ready to append stuff onDocumentReady(function () { (function (callback) { injectCss(config.injectorCss); initGoogle(callback); })(callback); }); }; (window.addEventListener) ? window.addEventListener('message', onMessage) : window.attachEvent('onmessage', onMessage); //Public functions module.sessionid = window.vsCartId || ''; module.onReady = onReady; module.isBlocker = isBlocker; module.initCart = initCart; module.initCartId = initCartId; module.cartContents = cartContents; module.showCart = showCart; module.hideCart = hideCart; module.addToCart = addItemToCart; module.injectHtml = injectHtml; module.outerIFrame = contentIframeHTML; module.qsParam = qsParam; module.injectFragmentFromServer = injectFragmentFromServer; module.cartInitialized = cartInitialized; return module; })(window); vsWineList = (function (window) { var initialized = false; function initInjector(container, force) { if (!initialized || force) { vinoShipperInjector.onReady(function () { var wineryId = window.vsWineryId; var cssFile = window.vsCssUrl || ''; var listId = window.vsWineListId || ''; var bustCache = window.vsBustCache || false; var padding = window.vsIFramePadding || ''; if (document.getElementById(container)) { var iframe = vinoShipperInjector.outerIFrame('Product List', '/iframe/v2/wine-list', cssFile, null, { wineryId: wineryId, listId: listId, bustCache: bustCache, padding: padding }); vinoShipperInjector.injectHtml(iframe, container); if (!document.getElementById('vs-cart')) vinoShipperInjector.initCart(); initialized = true; } }, true); } } return { init: initInjector, initialized: function () { return initialized; } }; })(window); vsWineClub = (function (window) { var initialized = false; function initInjector(container, force) { if (!initialized || force) { vinoShipperInjector.onReady(function () { var wineryId = window.vsWineryId; var cssFile = window.vsCssUrl || ''; var clubId = window.vsClubId || window.clubId || vinoShipperInjector.qsParam('clubId') || ''; var padding = window.vsIFramePadding; var preorder = window.vsPreorder; var clubIdLock = window.vsClubIdLock; var clubAllowList = window.vsClubAllowList; var iFrameTitle = 'Club Sign Up'; if (preorder) { iFrameTitle = 'Pre-Order Sign Up'; } if (document.getElementById(container)) { var iframe = vinoShipperInjector.outerIFrame(iFrameTitle, '/apps/registration/club/CLUB', cssFile, null, { wineryId: wineryId, clubId: clubId, preorder: preorder, clubIdLock: clubIdLock, clubAllowList: clubAllowList, padding: padding, callback: window.vsOnClubSignUpComplete }); vinoShipperInjector.injectHtml(iframe, container); initialized = true; } }, true); } } return { init: initInjector, initialized: function () { return initialized; } }; })(window); vsAddToCartButton = (function (window) { var module = {}; var addToCartButtonInitialized = false; function renderWidget(target) { var productId = target.getAttribute('data-product-id'); var wineryId = target.getAttribute('data-account-id') || target.getAttribute('data-winery-id'); var program = target.getAttribute('data-affinity-program'); var isMember = target.getAttribute('data-is-member'); var units = target.getAttribute('data-product-units') || ''; vinoShipperInjector.injectFragmentFromServer("/iframe/v3/add-to-cart-button?wineryId=" + wineryId + "&productId=" + productId + "&program=" + program + "&member=" + isMember + "&units=" + units, target); } function handleSubmit(event, form) { event.preventDefault(); var productId = form.productId ? form.productId.value : form.id.value; var quantity = 0; var minimumOrder = form.minimumOrder ? form.minimumOrder.value || 1 : 1; var landingPage = form.landingPage && form.landingPage.value ? form.landingPage.value : ''; for (var i = 0; i < form.elements.length; i++) { var el = form.elements[i]; if (el.name === 'quantity') { quantity += parseInt(el.value); } } quantity = quantity > 0 ? quantity : minimumOrder; vinoShipperInjector.addToCart(productId, quantity, landingPage); return false; } function initInjector(selector, force) { if (!addToCartButtonInitialized || force) { vinoShipperInjector.onReady(function () { var buttons = document.querySelectorAll(selector); for (var i = 0; i < buttons.length; i++) { renderWidget(buttons[i]); } if (!document.getElementById('vs-cart')) vinoShipperInjector.initCart(); addToCartButtonInitialized = true; }); } } //Communicate with the IFrame function onMessage(message) { vsLog(message); if (typeof message.data !== "string") return; if (message.data === 'canHazPostMessage') { document.getElementById(config.iframeId).contentWindow.postMessage('canHazPostMessage ack', "*"); } else if (message.data.indexOf('canHazPostMessage:') >= 0) { module.sessionid = message.data.split(':')[1]; vsLog('session id: ' + module.sessionid); window.parent.document.dispatchEvent(new CustomEvent('vsCartIdEvent', { detail: module.sessionid })); var itemCount = 0; vinoShipperInjector.cartContents(module.sessionid, function(qty){ itemCount = qty; }); // var itemCount = vinoShipperInjector.cartQty; var vsCartCountElement = window.document.getElementById('vs-cart-count'); if (vsCartCountElement && itemCount) { vsCartCountElement.innerText = itemCount.items; } } } (window.addEventListener) ? window.addEventListener('message', onMessage) : window.attachEvent('onmessage', onMessage); return { submit: handleSubmit, init: initInjector, sessionid: window.vsCartId || '' }; })(window); //////////////////////////// function init() { vinoShipperInjector.isBlocker(function (blocked) { if (blocked) { console.info('init', 'ads are blocked'); } else { console.info('init', 'ads are not blocked'); } }) } document.addEventListener('DOMContentLoaded', init, false); //////////////////////// vsSquarespace = (function (window) { var targetId = window.vsWineryId; var type = window.type; var module = {}; function isSquarespace() { if ((document.getElementsByTagName('head')[0].innerHTML.search("")) > -1) { console.log('Squarespace found'); return true; } return false; } function vsPageWatch() { MutationObserver = window.MutationObserver || window.WebKitMutationObserver; var a = new MutationObserver(function (a) { for (var b = 0; b < a.length; b++) { var c = a[b]; if ("attributes" === c.type) { var d = new Event("pageChange"); document.dispatchEvent(d); } } }); a.observe(document.body, { attributes: !0, attributeFilter: ["id"] }); } module.isSquarespace = isSquarespace; module.vsPageWatch = vsPageWatch; return module; })(window); vsIframeInit = (function () { if (vsSquarespace.isSquarespace()) { vsSquarespace.vsPageWatch(); document.addEventListener("pageChange", function () { if (document.getElementById("vs-winelist")) { vsWineList.init("vs-winelist", 1); } if (document.getElementById("vs-wineclub-signup")) { vsWineClub.init("vs-wineclub-signup", 1); } if (document.getElementsByClassName(".vs-add-to-cart")) { vsAddToCartButton.init(".vs-add-to-cart", 1); } }); } if (!vsWineList.initialized() && document.getElementById("vs-winelist")) vsWineList.init('vs-winelist'); if (!vsWineClub.initialized() && document.getElementById("vs-wineclub-signup")) vsWineClub.init('vs-wineclub-signup'); if (document.getElementsByClassName("vs-add-to-cart")) vsAddToCartButton.init('.vs-add-to-cart'); if (!vinoShipperInjector.cartInitialized && !vsWineClub.initialized()) { vinoShipperInjector.initCart(); } if (!vinoShipperInjector.cartIdInitialized) { vinoShipperInjector.initCartId(); } }); window.addEventListener ? window.addEventListener("load", vsIframeInit, false) : window.attachEvent && window.attachEvent("onload", vsIframeInit);