;(function () {
const GLOBAL_FLAG = ‘__HUPPA_WIDGET_IFRAME_LOADER_V1__’
if (window[GLOBAL_FLAG]) return
window[GLOBAL_FLAG] = true
const scriptEl = document.currentScript
if (!(scriptEl instanceof HTMLScriptElement) || !scriptEl.src) {
return
}
const token = scriptEl.getAttribute(‘data-token’) || window.HUPPA_WIDGET_TOKEN || ”
const position = scriptEl.getAttribute(‘data-position’) || window.HUPPA_WIDGET_POSITION || ‘center’
const themeAttr = scriptEl.getAttribute(‘data-theme’)
const themeGlobal = window.HUPPA_WIDGET_THEME
const resolveTheme = (value) => (value === ‘dark’ || value === ‘light’ ? value : undefined)
const theme = resolveTheme(themeAttr) || resolveTheme(themeGlobal) || ‘light’
const iframePath =
scriptEl.getAttribute(‘data-iframe-path’) ||
scriptEl.getAttribute(‘data-iframe-page’) ||
‘./widget-iframe.html’
const iframeUrl = new URL(iframePath, scriptEl.src)
if (token) iframeUrl.searchParams.set(’token’, token)
if (position) iframeUrl.searchParams.set(‘position’, position)
if (theme) iframeUrl.searchParams.set(’theme’, theme)
try {
const parentHref = window.location.href
if (parentHref) {
iframeUrl.searchParams.set(‘parentUrl’, parentHref)
const parentParams = new URL(parentHref).searchParams
const passthroughParams = [‘payment_id’, ‘button_id’, ‘showI18nKeys’]
for (const key of passthroughParams) {
const value = parentParams.get(key)
if (value) iframeUrl.searchParams.set(key, value)
}
}
} catch {
// ignore
}
const clamp = (value, min, max) => Math.min(Math.max(value, min), max)
const DEFAULT_COLLAPSED_WIDTH = 460
const DEFAULT_COLLAPSED_HEIGHT = 92
const MARGIN_PX = 12
const MIN_COLLAPSED_WIDTH = 340
let collapsedWidth = DEFAULT_COLLAPSED_WIDTH
let collapsedHeight = DEFAULT_COLLAPSED_HEIGHT
let isExpanded = false
const iframe = document.createElement(‘iframe’)
iframe.id = ‘huppa-widget-iframe’
iframe.title = ‘Huppa booking widget’
iframe.src = iframeUrl.href
iframe.loading = ‘lazy’
iframe.referrerPolicy = ‘strict-origin-when-cross-origin’
const applyBaseStyles = () => {
iframe.style.border = ‘0’
iframe.style.background = ’transparent’
iframe.style.overflow = ‘hidden’
iframe.style.zIndex = ‘2147483647’
}
const applyCollapsedPosition = () => {
iframe.style.position = ‘fixed’
iframe.style.top = ‘auto’
iframe.style.right = ‘auto’
iframe.style.bottom = `${MARGIN_PX}px`
iframe.style.left = ‘auto’
if (position === ‘left’) {
iframe.style.left = `${MARGIN_PX}px`
iframe.style.transform = ‘none’
return
}
if (position === ‘right’) {
iframe.style.right = `${MARGIN_PX}px`
iframe.style.transform = ‘none’
return
}
iframe.style.left = ‘50%’
iframe.style.transform = ’translateX(-50%)’
}
const applyCollapsedSize = () => {
const maxWidth = Math.max(0, window.innerWidth – MARGIN_PX * 2)
const maxHeight = Math.max(0, window.innerHeight – MARGIN_PX * 2)
const width = clamp(collapsedWidth, MIN_COLLAPSED_WIDTH, maxWidth || DEFAULT_COLLAPSED_WIDTH)
const height = clamp(collapsedHeight, 73, maxHeight || DEFAULT_COLLAPSED_HEIGHT)
iframe.style.width = `${width}px`
iframe.style.height = `${height}px`
}
const applyExpandedStyles = () => {
iframe.style.position = ‘fixed’
iframe.style.inset = ‘0’
iframe.style.top = ‘0’
iframe.style.right = ‘0’
iframe.style.bottom = ‘0’
iframe.style.left = ‘0’
iframe.style.width = ‘100vw’
iframe.style.height = ‘100vh’
iframe.style.transform = ‘none’
}
const render = () => {
applyBaseStyles()
if (isExpanded) {
applyExpandedStyles()
} else {
applyCollapsedPosition()
applyCollapsedSize()
}
}
const setExpanded = (expanded) => {
isExpanded = Boolean(expanded)
render()
}
const mount = () => {
if (!document.body) return
if (document.getElementById(iframe.id)) return
document.body.appendChild(iframe)
render()
}
if (document.readyState === ‘loading’) {
document.addEventListener(‘DOMContentLoaded’, mount, { once: true })
} else {
mount()
}
window.addEventListener(‘resize’, () => {
render()
})
window.addEventListener(‘message’, (event) => {
if (event.source !== iframe.contentWindow) return
const data = event.data
if (!data || typeof data !== ‘object’) return
if (data.__huppaWidget !== true || data.version !== 1) return
if (data.type === ‘state’ && typeof data.expanded === ‘boolean’) {
setExpanded(data.expanded)
return
}
if (data.type === ‘resize’) {
if (typeof data.width === ‘number’ && Number.isFinite(data.width)) {
collapsedWidth = Math.ceil(data.width)
}
if (typeof data.height === ‘number’ && Number.isFinite(data.height)) {
collapsedHeight = Math.ceil(data.height)
}
if (!isExpanded) render()
return
}
if (data.type === ‘navigate’ && typeof data.url === ‘string’ && data.url) {
window.location.assign(data.url)
}
})
})()