UNPKG

@agility/web-studio-sdk

Version:

Standard Development Kit used to enable Web Studio features in Agility CMS

133 lines (121 loc) 4.02 kB
import { initComponents, initializePreview } from "./util" import { dispatchDecoratorMapUpdatedEvent, dispatchNavigationEvent, INavigationEventArgs, } from "./util/frameEvents" import { generateDecoratorMap } from "./util/generateDecoratorMap" /** * Agility Preview SDK * This works by putting agility-data-* attributes on various elements in your markup. */ let isInitialized = false const setIsInitialized = (state: boolean) => { isInitialized = state startObserver() } let isDocumentReady = false const setDocumentReady = (state: boolean) => { isDocumentReady = state startObserver() } const onLocationChange = () => { const agilityPageIDElem = document.querySelector("[data-agility-page]") const agilityDynamicContentElem = document.querySelector( "[data-agility-dynamic-content]" ) //initialize pageID and contentID let pageID: any = -1 let contentID: any = -1 //if agilityPageIDElem exists, get the pageID from its data attribute if (agilityPageIDElem) { pageID = parseInt(agilityPageIDElem.getAttribute("data-agility-page") || "") } //don't proceed if we don't have a valid pageID if (isNaN(pageID) || pageID < 1) { console.warn( "%cWeb Studio SDK\n - no pageID found on the `data-agility-page` element. \nMake sure you have an element set up like this: data-agility-page='{{agilitypageid}}' .", "font-weight: bold" ) return } //if agilityDynamicContentElem exists, get the contentID from its data attribute if (agilityDynamicContentElem) { contentID = agilityDynamicContentElem.getAttribute( "data-agility-dynamic-content" ) } //prepare the full URL without query parameters let fullUrl = location.href if (fullUrl.indexOf("?") > -1) { fullUrl = fullUrl.substring(0, fullUrl.indexOf("?")) } //create the navigation event arguments const args: INavigationEventArgs = { url: fullUrl, pageID, contentID, windowScrollableHeight: document.documentElement.scrollHeight, windowHeight: window.innerHeight, } //dispatch the navigation event dispatchNavigationEvent(args) //initialize the components that may have reloaded initComponents() //generate the decorator map const decoratorMap = generateDecoratorMap() //send the decorator map to the parent if (decoratorMap) { dispatchDecoratorMapUpdatedEvent({ decoratorMap }) } } const startObserver = () => { if (!isDocumentReady || !isInitialized) return const observer = new MutationObserver((target, options) => { if (isInitialized) { //Debounce the location change; we don't want to send multiple navigation events; setTimeout(() => { onLocationChange() }, 100) } }) // start observing the body observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [ "data-agility-page", "data-agility-dynamic-content", "data-agility-guid", "data-agility-field", "data-agility-component", "data-agility-html", "data-agility-previewbar", ], }) } // Check immediately if the document is already in an interactive or complete state // This ensures that if the script runs after the document is already loaded, // we don't miss the opportunity to initialize the app. if ( document.readyState === "complete" || document.readyState === "interactive" ) { setDocumentReady(true) } // Add a listener for changes in the document's ready state. // This is necessary to handle cases where the document hasn't yet reached the // interactive or complete state when the script is first executed. document.onreadystatechange = () => { // If the document's readyState becomes 'interactive' or 'complete', // it means the DOM is ready, so we can safely initialize our observer. if ( document.readyState === "interactive" || document.readyState === "complete" ) { setDocumentReady(true) } } // Needs to always happen initializePreview({ setIsInitialized })