const body = document.body; const widgetUrl = new URL("https:\/\/integrations.winespot.ai\/chat\/widget.php?pid=8801a9ec-7bde-4f28-bdf9-5eca765ba06f&v=37ae9bf0ec"); const hostOrigin = window.location.origin; widgetUrl.searchParams.set('host_origin', hostOrigin); const widgetOrigin = widgetUrl.origin; const winespot = document.createElement('iframe'); winespot.id = 'winespot'; winespot.sandbox = 'allow-scripts allow-same-origin allow-popups'; winespot.allow = 'clipboard-write'; winespot.src = widgetUrl.toString(); winespot.style.display = 'none'; body.appendChild(winespot); const medal = document.createElement('iframe'); medal.id = 'wsf_medal'; medal.sandbox = 'allow-scripts allow-same-origin'; medal.style.display = 'none'; medal.setAttribute('srcdoc','
'); body.appendChild(medal); medal.setAttribute('style','display:block'); body.insertAdjacentHTML('beforeend',` `); const capabilities = { state: true, resize: true, openLink: true, viewport: true, medalClick: true }; const utoken = new URLSearchParams(window.location.search).get('utoken') || ''; const sessionId = globalThis.crypto?.randomUUID ? globalThis.crypto.randomUUID() : 'ws_' + Math.random().toString(36).slice(2) + Date.now().toString(36); let handshakeReady = false; let lastViewport = ''; let currentState = 'closed'; const allowedProtocols = ['http:', 'https:']; const sendToWidget = (type, payload = {}) => { const target = winespot.contentWindow; if(!target) return; target.postMessage({ type, payload }, widgetOrigin); }; const updateMedalIcon = (isOpen) => { if(isOpen) { body.classList.add('-chatOpened'); } else { body.classList.remove('-chatOpened'); } try { const medalDoc = medal.contentDocument; const backIcon = medalDoc?.getElementById('back-icon'); if(backIcon) { if(isOpen) { backIcon.classList.add('active'); } else { backIcon.classList.remove('active'); } } } catch (err) {} }; const setState = state => { const nextState = state || 'closed'; if(currentState === nextState) return; currentState = nextState; if(nextState === 'closed') { winespot.style.display = 'none'; winespot.classList.remove('-opened','-hello'); medal.classList.remove('-chatOpened'); updateMedalIcon(false); return; } winespot.style.display = 'block'; if(nextState === 'hello') { winespot.classList.add('-hello'); winespot.classList.remove('-opened'); medal.classList.remove('-chatOpened'); updateMedalIcon(false); applyResize(); return; } winespot.classList.add('-opened'); winespot.classList.remove('-hello'); medal.classList.add('-chatOpened'); updateMedalIcon(true); applyResize(); }; const getViewportType = () => { const width = window.innerWidth; if(width < 450) { return 'isMobile'; } if(width < 768) { return 'isTablet'; } if(window.innerHeight < 850) { return 'isLaptop'; } return ''; }; const broadcastViewport = (force = false) => { const nextType = getViewportType(); if(!force && nextType === lastViewport) return; lastViewport = nextType; if(handshakeReady) { sendToWidget('WS:VIEWPORT', { type: nextType }); } }; let requestedHeight = 700; const getWidgetBottom = () => { if(window.innerWidth < 450) return 0; if(winespot.classList.contains('-hello')) return 90; return 116; }; const applyResize = height => { const parsed = parseInt(height, 10); if(Number.isFinite(parsed)) { requestedHeight = parsed; } const targetHeight = winespot.classList.contains('-hello') ? 180 : requestedHeight; const topGap = 20; const maxHeight = Math.max(0, window.innerHeight - getWidgetBottom() - topGap); const minHeight = 180; const finalHeight = maxHeight < minHeight ? maxHeight : Math.max(minHeight, Math.min(targetHeight, maxHeight)); winespot.style.height = Math.max(0, Math.floor(finalHeight)) + 'px'; }; const openLink = href => { if(!href) return; try { const url = new URL(href, window.location.origin); if(!allowedProtocols.includes(url.protocol)) return; window.open(url.toString(), '_blank'); } catch (err) {} }; const handleHello = payload => { const nonce = payload?.nonce; handshakeReady = false; sendToWidget('WS:HELLO_ACK', { sessionId, nonce, utoken, capabilities, url: window.location.href, }); handshakeReady = true; broadcastViewport(true); }; const handleMessage = event => { if(event.origin !== widgetOrigin || event.source !== winespot.contentWindow) return; const { type, payload = {}, sessionId: messageSessionId } = event.data || {}; if(type === 'WS:HELLO') { handleHello(payload); return; } if(!handshakeReady || messageSessionId !== sessionId) return; if(type === 'WS:STATE') { setState(payload?.state); } else if(type === 'WS:RESIZE') { applyResize(payload?.height); } else if(type === 'WS:OPEN_LINK') { openLink(payload?.href); } else if(type === 'WS:CHANGE_LINK') { window.history.replaceState({ path: payload?.url, type: 'clean' }, '', payload?.url); } }; let resizeTimeout; window.addEventListener('resize', () => { clearTimeout(resizeTimeout); resizeTimeout = setTimeout(() => { broadcastViewport(); applyResize(); }, 150); }); medal.addEventListener('load', () => { try { const medalDoc = medal.contentDocument; const medalBody = medalDoc?.body; if(medalBody) { medalBody.classList.add('-loaded'); } const medalEl = medalDoc?.getElementById('ws_medal'); if(medalEl) { medalEl.addEventListener('click', () => { if(!handshakeReady) return; sendToWidget('WS:MEDAL_CLICK', {}); }); } if(currentState === 'open') { body.classList.add('-chatOpened'); const backIcon = medalDoc?.getElementById('back-icon'); if(backIcon) { backIcon.classList.add('active'); } } } catch (err) {} }); window.addEventListener('message', handleMessage); setState('closed');