"use strict"; class ConModalEce { options = { selectElement: false, iframeUrl: "", width: "500", modalTitle: "", showOverlay: true, closeOnOverlayClick: true, closeOnEscape: true, trueIframeHeight: true, animationMode: "ff_fade_in", fullscreen: true, vinNumAttr: "", headerBgColor: "#000", closeBtn: true, enableMobileFullHeight: false }; modal; styles = {}; constructor(userInputOptions) { if (typeof this.options === "object") this.options = { ...this.options, ...userInputOptions }; this.modal = document.createElement("div"); this.modal.classList.add("ff_modal"); this.styles.modalStyle = `visibility:hidden;`; this.styles.closeStyle = `position: absolute; top: -31px; right: 2px; cursor: pointer; z-index: 1; border: none; outline: none; width: 30px; height: 30px; background: rgb(0, 0, 0); display: flex; align-items: center; justify-content: center; color: rgb(255, 255, 255); border-radius: 50%; font-size: 10px;`; this.styles.headerStyle = `position: relative; padding: 5px; font-size: 12px; background-color: ${this.options.headerBgColor}; color: ${this.getContrastColor(this.options.headerBgColor || '#000')};`; this.styles.bodyStyle = `position: relative; background: white; color: black; padding: 10px; font-size: 20px;`; this.styles.iframeStyle = `position: relative; width: 100%;border: none;`; this.init(); this.manageScreenSize.bind(this); // add styles to head const style = document.createElement("style"); style.innerText = `.ff_modal{ z-index: 999999; width: 100%; height: 100%; position: fixed; display: grid; place-items:center; inset:0; overflow: auto; } .loader { border: 8px solid #f3f3f3; z-index:99999; border-top: 8px solid #3498db; border-radius: 50%; width: 60px; height: 60px; animation: spin 2s linear infinite; position: fixed; top:calc(50% - 30px); left: calc(50% - 30px); z-index: 99999; transform: translate(-50%, -50%); } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } html.ff_modal_open::after {z-index:9999; content: ''; position: fixed; inset: 0; background: #000000ad; } .ff_fade_in { animation: fadeIn 800ms ease-in; } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } .ff_modal.ff_mobile iframe { height: 100% !important; } .ff_modal_open {overflow:hidden;} .modal-body {height:auto;} .ff_mobile .modal-body {height:100%;padding:0 !important;}@media (height <= 665px) { .ff_modal .modal-body { max-width: 1075px !important; } }`; document.head.appendChild(style); } init() { // close modal on escape if (this.options.closeOnEscape) { document.addEventListener("keydown", (e) => { if (e.key === "Escape") { this.closeModal(); } }); } // close modal on click outside this.modal.addEventListener('click', (e) => { if (e.target === this.modal && this.options.closeOnOverlayClick) { this.closeModal(); } }); if (this.options.enableMobileFullHeight) { this.manageScreenSize(); // this.appendCss('@media(max-width:640px){ #flick_frame {height: 100vh !important;} }'); } window.addEventListener('resize', this.manageScreenSize.bind(this)); setTimeout(() => { this.buildModal(); }, 200); this.listenMessage(); this.sendMessage(); } buildModal() { // create loader div const loader = document.createElement("div"); loader.classList.add("loader"); document.body.appendChild(loader); // document.body.classList.add("ff_modal_open"); document.documentElement.classList.add("ff_modal_open"); this.modal.style.cssText += this.styles.modalStyle; if (this.options.animationMode) this.modal.classList.add(this.options.animationMode); if (this.options.width) this.modal.style.width = `${this.options.width}px`; if (this.options.modalTitle) { const modalHeader = document.createElement("div"); modalHeader.classList.add("modal-header"); modalHeader.style.cssText = this.styles.headerStyle; this.modal.append(modalHeader); const modalTitle = document.createElement("h2"); modalTitle.style.cssText = 'margin: 0px; font-weight: normal;'; modalTitle.classList.add("modal-title"); modalTitle.innerText = this.options.modalTitle || ""; modalHeader.appendChild(modalTitle); } // create modal body const modalBody = document.createElement("div"); modalBody.classList.add("modal-body"); modalBody.style.width = "100%"; modalBody.style.position = "relative"; modalBody.style.maxWidth = `${this.options.width}`; this.modal.appendChild(modalBody); // create close button if (this.options.closeBtn) { const closeBtn = document.createElement("button"); closeBtn.classList.add("close-btn"); closeBtn.style.cssText = this.styles.closeStyle; closeBtn.innerHTML = "✖"; modalBody.appendChild(closeBtn); // add event listeners closeBtn.addEventListener("click", () => { this.closeModal(); }); } // create iframe const iframe = document.createElement('iframe'); iframe.style.cssText = "width: 100%; height: 100%; border: none;display:block;"; iframe.src = this.options.iframeUrl || ""; iframe.id = "flick_frame"; iframe.setAttribute("allowfullscreen", "true"); iframe.setAttribute("frameborder", "0"); iframe.setAttribute("scrolling", "no"); iframe.setAttribute("allowtransparency", "true"); modalBody.appendChild(iframe); document.body.appendChild(this.modal); let isLandscape = window.matchMedia("(orientation: landscape)").matches; if (screen.orientation) isLandscape = screen.orientation.type.includes('landscape'); const isMobile = this.detectMobile(); const deviceInfo = isMobile ? 'mobile' : 'desktop'; const pageProps = { action: "ff_page_props", orientation: isLandscape ? "landscape" : "portrait", width: window.innerWidth, device: deviceInfo }; if (iframe) { iframe.addEventListener('load', () => { iframe.contentWindow?.postMessage(pageProps, "*"); setTimeout(() => { iframe.contentWindow?.postMessage(pageProps, "*"); }, 500); setTimeout(() => { iframe.contentWindow?.postMessage(pageProps, "*"); }, 1000); setTimeout(() => { iframe.contentWindow?.postMessage(pageProps, "*"); }, 1500); }); } window.addEventListener("orientationchange", () => { setTimeout(() => { this.sendMessage(); }, 500); }); if (screen.orientation) { screen.orientation.addEventListener("change", () => { setTimeout(() => { this.sendMessage(); }, 500); }); } } listenMessage() { window.addEventListener("message", (e) => { const message = e.data; if (message.page) { if (this.modal.style.visibility === "hidden") this.modal.style.visibility = "visible"; if (document.querySelector('.loader')) document.querySelector('.loader')?.remove(); this.applyPageProperties(message); } if (message?.data?.ff_height) { // console.log(message?.data?.ff_height); this.modal.querySelector('iframe').style.height = `${message?.data?.ff_height}px`; } }); } sendMessage() { let isLandscape = window.matchMedia("(orientation: landscape)").matches; const isMobile = this.detectMobile(); const deviceInfo = isMobile ? 'mobile' : 'desktop'; if (screen.orientation) isLandscape = screen.orientation.type.includes('landscape'); if (window.innerWidth < 590) isLandscape = false; const pageProps = { action: "ff_page_props", orientation: isLandscape ? "landscape" : "portrait", width: window.innerWidth, device: deviceInfo }; if (this.modal.querySelector('iframe')) { this.modal.querySelector('iframe').contentWindow?.postMessage(pageProps, "*"); } } closeModal() { // document.body.classList.remove("ff_modal_open"); document.documentElement.classList.remove("ff_modal_open"); this.modal.remove(); } getContrastColor(hex) { hex = hex.slice(1); const r = parseInt(hex.substring(0, 2), 16); const g = parseInt(hex.substring(2, 4), 16); const b = parseInt(hex.substring(4, 6), 16); const sum = Math.round(((r * 299) + (g * 587) + (b * 114)) / 1000); return (sum > 128) ? '#000' : '#fff'; } manageScreenSize() { this.sendMessage(); if (this.detectMobile()) { this.modal.classList.add('ff_mobile'); document.body.classList.add('ff_mobile'); } else { this.modal.classList.remove('ff_mobile'); document.body.classList.remove('ff_mobile'); } } detectMobile = () => { let isMobile = /iPhone|iPod|Android/i.test(navigator.userAgent.toLowerCase()); let screenSize = this.detectScreenSize(); let orientation = this.detectOrientation(); if (screenSize === 'small') isMobile = true; if ((screenSize === 'medium' && orientation === 'portrait') || (screenSize === 'large' && orientation === 'landscape')) { isMobile = false; } // if ((screenSize === 'medium' && orientation === 'portrait')) { // isMobile = false; // } return isMobile; }; detectOperatingSystem = () => { const userAgent = navigator.userAgent || navigator.vendor || window.opera; return /iPad|iPhone|iPod/.test(userAgent) && !window.MSStream ? 'iOS' : 'Android'; }; detectOrientation = () => { // let isDeviceLandscape = window.matchMedia("(orientation: landscape)").matches; // if (screen.orientation) // isDeviceLandscape = screen.orientation.type.includes('landscape'); // console.log('isDeviceLandscape---------', isDeviceLandscape); // console.log('window.matchMedia("(orientation: landscape)").matches---------', window.matchMedia("(orientation: landscape)").matches); return (window.matchMedia("(orientation: landscape)").matches || screen?.orientation?.type.includes('landscape')) ? 'landscape' : 'portrait'; }; detectScreenSize() { const sm = window.matchMedia("(max-width: 590px)"); const md = window.matchMedia("(min-width: 590px) and (max-width: 1000px)"); const lg = window.matchMedia("(min-width: 1000px)"); if (sm.matches) { return 'small'; } else if (md.matches) { return 'medium'; } else if (lg.matches) { return 'large'; } else { return 'unknown'; } } applyPageProperties(msg) { const modalType = msg?.page; switch (modalType) { case 'lp': this.buildLandingPage(); break; case 'aspect_ratio': this.buildAspectRatioPage(msg); break; default: break; } } buildLandingPage() { this.modal.querySelector('.modal-body').style.cssText = `width:95%;max-width:auto;`; this.modal.querySelector('iframe').style.height = '95vh'; } buildAspectRatioPage(msg) { this.modal.querySelector('.modal-body').style.cssText = `max-height:95vh; width:100%;max-width:${this.options.width}; aspect-ratio:${msg?.data}`; } appendCss(styleRules) { const style = document.createElement('style'); style.innerHTML = styleRules; document.head.appendChild(style); } } // export default ConModal;