ibembed
Version:
Instabook Embed JavaScript SDK
1 lines • 17.2 kB
Source Map (JSON)
{"version":3,"file":"instabook.es.mjs","sources":["../src/types/common.ts","../src/InstabookEmbed.ts","../src/utils/common.ts"],"sourcesContent":["export interface EmbedParams {\r\n [key: string]: any\r\n}\r\n\r\nexport interface EmbedOption {\r\n id: string;\r\n version?: string;\r\n businessID: string;\r\n fitContent?: boolean;\r\n showLoader?: boolean;\r\n locale?: string;\r\n appearance?: string;\r\n customCSS?: string | string[];\r\n embedParams?: EmbedParams;\r\n}\r\n\r\n// Define event types\r\nexport enum EventType {\r\n IFRAME_LOAD = \"iframe:load\",\r\n EMBED_IFRAME_READY = \"iframe:ready\",\r\n IFRAME_ERROR = \"iframe:error\",\r\n IFRAME_RESIZE = \"iframe:resize\",\r\n}\r\n\r\nexport interface IframeResizeType {\r\n height: number;\r\n}\r\n\r\nexport interface EventDataMap {\r\n [EventType.EMBED_IFRAME_READY]?: any;\r\n [EventType.IFRAME_ERROR]?: any;\r\n [EventType.IFRAME_LOAD]?: any;\r\n [EventType.IFRAME_RESIZE]?: IframeResizeType;\r\n}\r\n// Define callback interface\r\n// Define callback interface based on event data\r\nexport type EventCallbacks = {\r\n [K in keyof EventDataMap]?: ((data: EventDataMap[K]) => void)[];\r\n};\r\n","import { EmbedOption, EmbedParams, EventCallbacks, EventType, EventDataMap, IframeResizeType } from \"./types/common\";\r\nimport { debounce } from \"./utils/common\";\r\n\r\nconst InstabookSource = \"instabook-embed\";\r\n\r\nconst loaderStyle = document.createElement(\"style\");\r\nloaderStyle.textContent = `\r\n .ib-iframe-loader {\r\n position: absolute;\r\n display: none;\r\n left: 50%;\r\n top: 50%;\r\n transform: translate(-50%,-50%);\r\n z-index: 1;\r\n }\r\n .ib-iframe-container {\r\n transition: height 0.5s ease;\r\n position: relative;\r\n min-height: 100%;\r\n }\r\n `;\r\ndocument.head.appendChild(loaderStyle);\r\n\r\nexport default class InstabookEmbed extends EventTarget {\r\n\r\n iframe: HTMLIFrameElement | undefined;\r\n iframeContainer: HTMLElement | null;\r\n loaderElement?: HTMLElement | null;\r\n iframeId: string;\r\n options: EmbedOption;\r\n private isReady = false;\r\n eventCallbacks: EventCallbacks = {};\r\n customStyles: HTMLStyleElement | null = null;\r\n\r\n constructor(options: EmbedOption) {\r\n super();\r\n this.handleMessage = this.handleMessage.bind(this);\r\n this.init = this.init.bind(this);\r\n this.reload = this.reload.bind(this);\r\n this.addEventListener = this.addEventListener.bind(this);\r\n this.removeEventListener = this.removeEventListener.bind(this);\r\n if (!options) {\r\n throw Error('Options required');\r\n }\r\n const { id } = options;\r\n if (!id) {\r\n throw Error('container id is required');\r\n }\r\n if (!options.businessID) {\r\n throw Error('business id is required');\r\n }\r\n this.iframeContainer = document.getElementById(id);\r\n if (!this.iframeContainer) {\r\n throw Error('Container does not exist');\r\n }\r\n this.iframeId = id;\r\n options.version = options.version || 'live';\r\n\r\n this.options = options;\r\n\r\n }\r\n\r\n init () {\r\n // Create the iframe\r\n this.createIframe(this.options.embedParams);\r\n }\r\n\r\n\r\n // Register callback for a specific event type\r\n on<T extends EventType>(eventType: T, callback: (eventData?: EventDataMap[T]) => void) {\r\n this.eventCallbacks[eventType] = [callback];\r\n }\r\n\r\n // Remove an event listener for a specific event type\r\n removeEventListener<T extends EventType>(eventType: T, callback: (data: EventDataMap[T]) => void) {\r\n const callbacks = this.eventCallbacks[eventType];\r\n if (callbacks) {\r\n this.eventCallbacks[eventType] = callbacks.filter(cb => cb !== callback);\r\n }\r\n }\r\n\r\n addEventListener<T extends EventType>(eventType: T, callback: (data: EventDataMap[T]) => void) {\r\n if (!this.eventCallbacks[eventType]) {\r\n this.eventCallbacks[eventType] = [];\r\n }\r\n this.eventCallbacks[eventType]?.push(callback);\r\n }\r\n\r\n private triggerEvent<T extends EventType>(eventType: T, eventData?: EventDataMap[T]) {\r\n if (this.isReady) {\r\n const callbacks = this.eventCallbacks[eventType] || [];\r\n callbacks.forEach(callback => callback(eventData));\r\n }\r\n }\r\n\r\n // Stop the video\r\n reload () {\r\n this.sendMessage(\"reload\", null);\r\n }\r\n\r\n // Get video duration\r\n getSomething () {\r\n return 1;\r\n }\r\n\r\n // Send a message to the iframe\r\n sendMessage (message: string, data: any) {\r\n if (!this.isReady) {\r\n return;\r\n }\r\n const jsonData = data === null ? \"\" : data;\r\n const messageObject = {\r\n msg: message,\r\n source: InstabookSource,\r\n id: this.iframeId,\r\n data: jsonData\r\n };\r\n if (this.iframe && this.iframe.contentWindow) {\r\n this.iframe.contentWindow.postMessage(messageObject, \"https://instabook.io\");\r\n } else {\r\n throw Error('Iframe did not load the content');\r\n }\r\n }\r\n\r\n// Event handler for messages\r\n private handleMessage (event: MessageEvent) {\r\n if (!this.isReady) {\r\n return;\r\n }\r\n try {\r\n const eventData = event.data;\r\n\r\n if (\r\n event.source === this.iframe?.contentWindow &&\r\n eventData.source === InstabookSource &&\r\n event.origin === 'https://instabook.io'\r\n ) {\r\n const eventType = eventData.type;\r\n switch (eventType) {\r\n case \"iframe:ready\":\r\n this.onReady();\r\n break;\r\n case \"iframe:error\":\r\n this.onError(eventData.data);\r\n break;\r\n case \"iframe:resize\":\r\n this.onResize(eventData.data);\r\n break;\r\n }\r\n }\r\n } catch (error) {\r\n // Handle message parsing error\r\n }\r\n }\r\n buildQueryString ({ params, origin }: { params?: EmbedParams, origin: string}) {\r\n let queryString = \"?remoteEmbed=true&remoteHost=\" +\r\n encodeURIComponent(origin);\r\n if (params) {\r\n for (const key in params) {\r\n queryString += \"&\" + encodeURIComponent(key) + \"=\" + encodeURIComponent(params[key]);\r\n }\r\n }\r\n queryString += `&t=${Date.now()}`\r\n return queryString;\r\n }\r\n\r\n private onResize (data: IframeResizeType) {\r\n this.triggerEvent(EventType.IFRAME_RESIZE, data);\r\n if (this.options.fitContent) {\r\n debounce(300, (data: IframeResizeType) => {\r\n if (this.isReady && this.iframeContainer && this.options.fitContent) {\r\n this.iframeContainer.style.height = `${data.height + 80}px`\r\n }\r\n })(data);\r\n }\r\n }\r\n\r\n private onReady () {\r\n this.triggerEvent(EventType.EMBED_IFRAME_READY);\r\n if (this.loaderElement) {\r\n this.loaderElement.style.display = 'none';\r\n }\r\n }\r\n\r\n private onLoad () {\r\n this.triggerEvent(EventType.IFRAME_LOAD);\r\n if (this.loaderElement) {\r\n this.loaderElement.style.display = 'none';\r\n }\r\n }\r\n\r\n private onError (e: any) {\r\n this.triggerEvent(EventType.IFRAME_ERROR, e);\r\n if (this.loaderElement) {\r\n this.loaderElement.style.display = 'none';\r\n }\r\n }\r\n\r\n // Create the iframe\r\n private createIframe (embedParams?: EmbedParams) {\r\n\r\n if (!this.iframeContainer) {\r\n throw Error('Container does not exist');\r\n }\r\n let origin = \"\".concat(location.protocol, \"//\").concat(location.hostname);\r\n if (location.port) {\r\n origin += \":\".concat(location.port);\r\n }\r\n\r\n const baseUrl = this.options.version === 'live' ? 'https://instabook.io/e1/' : `https://instabook.io/version-${this.options.version}/e1/`;\r\n\r\n const embedUrl =\r\n baseUrl +\r\n this.options.businessID +\r\n this.buildQueryString({params: embedParams, origin});\r\n\r\n // Create the iframe element\r\n this.iframe = document.createElement(\"iframe\");\r\n this.iframe.src = embedUrl;\r\n this.iframe.allow = \"fullscreen\";\r\n this.iframe.scrolling = this.options.fitContent ? 'no' : 'yes';\r\n this.iframe.setAttribute(\"style\", \"width: 100%; height: 100%; border: 0px; position: absolute;\")\r\n\r\n this.iframeContainer.classList.add('ib-iframe-container');\r\n this.iframeContainer.appendChild(this.iframe);\r\n this.loaderElement = this.iframeContainer.querySelector('.ib-iframe-loader') as HTMLElement;\r\n\r\n if (this.options.showLoader && this.loaderElement) {\r\n this.loaderElement.style.display = 'block';\r\n }\r\n this.iframe.onload = this.onLoad.bind(this);\r\n this.iframe.onerror = this.onError.bind(this);\r\n this.isReady = true;\r\n // Add message event listener\r\n window.removeEventListener(\"message\", this.handleMessage, false);\r\n window.addEventListener(\"message\", this.handleMessage, false);\r\n }\r\n\r\n reset() {\r\n if (!this.isReady) {\r\n return;\r\n }\r\n if (this.iframeContainer && this.iframe) {\r\n // Remove iframe from the container\r\n this.iframeContainer.removeChild(this.iframe);\r\n this.iframeContainer.classList.remove('ib-iframe-container');\r\n this.iframe = undefined;\r\n }\r\n\r\n if (this.customStyles) {\r\n // Remove the custom styles when destroying\r\n this.customStyles.remove();\r\n this.customStyles = null;\r\n }\r\n\r\n if (this.loaderElement) {\r\n this.loaderElement.style.display = 'none';\r\n }\r\n\r\n // Remove message event listener\r\n window.removeEventListener(\"message\", this.handleMessage, false);\r\n\r\n // Reset event callbacks\r\n this.eventCallbacks = {};\r\n this.isReady = false;\r\n\r\n }\r\n}\r\n","export function debounce<T extends (...args: any[]) => void>(\r\n wait: number,\r\n callback: T,\r\n immediate = false,\r\n) {\r\n // This is a number in the browser and an object in Node.js,\r\n // so we'll use the ReturnType utility to cover both cases.\r\n let timeout: ReturnType<typeof setTimeout> | null;\r\n\r\n return function <U>(this: U, ...args: Parameters<typeof callback>) {\r\n // eslint-disable-next-line @typescript-eslint/no-this-alias\r\n const context = this;\r\n const later = () => {\r\n timeout = null;\r\n\r\n if (!immediate) {\r\n callback.apply(context, args);\r\n }\r\n };\r\n const callNow = immediate && !timeout;\r\n\r\n if (typeof timeout === \"number\") {\r\n clearTimeout(timeout);\r\n }\r\n\r\n timeout = setTimeout(later, wait);\r\n\r\n if (callNow) {\r\n callback.apply(context, args);\r\n }\r\n };\r\n}\r\n"],"names":["EventType","InstabookSource","loaderStyle","document","createElement","textContent","head","appendChild","InstabookEmbed","EventTarget","constructor","options","super","this","isReady","eventCallbacks","customStyles","handleMessage","bind","init","reload","addEventListener","removeEventListener","Error","id","businessID","iframeContainer","getElementById","iframeId","version","createIframe","embedParams","on","eventType","callback","callbacks","filter","cb","push","triggerEvent","eventData","forEach","sendMessage","getSomething","message","data","jsonData","messageObject","msg","source","iframe","contentWindow","postMessage","event","origin","type","onReady","onError","onResize","error","buildQueryString","params","queryString","encodeURIComponent","key","Date","now","IFRAME_RESIZE","fitContent","wait","immediate","timeout","args","context","callNow","clearTimeout","setTimeout","apply","debounce","style","height","EMBED_IFRAME_READY","loaderElement","display","onLoad","IFRAME_LOAD","e","IFRAME_ERROR","concat","location","protocol","hostname","port","embedUrl","src","allow","scrolling","setAttribute","classList","add","querySelector","showLoader","onload","onerror","window","reset","removeChild","remove","undefined"],"mappings":"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"}