const DAS = window.DAS || { documentLoaded: false, staticUrl: "", MAX_TT: 500, ttParentsApplied: {}, tooltipElement: undefined, tooltipContent: undefined, dossierURL: undefined, resizeCfg: { tracking: false, startWidth: null, minWidth: 200, startCursorScreenX: null, resizeTarget: null, handle: undefined, handleOverflow: undefined, }, }; window.addEventListener("DOMContentLoaded", function () { DAS.tooltipElement = document.getElementById("tooltip-wrapper"); DAS.tooltipContent = document.getElementById("tooltip-content"); DAS.dossierURL = document.location.href?.replace("index.html", ""); init(); }); window.addEventListener("load", () => { const rmlid = document.body.dataset["rmlid"] || null; const meta = { type: "substance", id: rmlid, }; window.parent.postMessage( { type: "dossierIF.loaded", details: { meta, }, }, "*" ); }); function init() { const expander = document.getElementById("das-expand-all"); const colapser = document.getElementById("das-collapse-all"); const toc = document.getElementById("das-dossier-sidebar"); const allCollapsible = document.querySelectorAll( ".das-nav-topsection ~ .collapse" ); const allCollapsibleTriggers = document.querySelectorAll(".das-nav-header"); DAS.resizeCfg.handle = document.querySelector(".das-resize-handle"); DAS.resizeCfg.resizeTarget = document.querySelector( ".das-dossier-sidebar-container" ); DAS.resizeCfg.handleOverflow = document.querySelector(".handle-overflow"); DAS.resizeCfg.handle.addEventListener("mousedown", (event) => { // we need an overflow element to fill the content space, // otherwise the dossier document object will not catch the events // over the iframe content space DAS.resizeCfg.handleOverflow.style.width = "100vw"; DAS.resizeCfg.startCursorScreenX = event.screenX; DAS.resizeCfg.startWidth = +DAS.resizeCfg.resizeTarget?.getBoundingClientRect()?.width; DAS.resizeCfg.tracking = true; document.addEventListener("mousemove", handleResizeMousemove, false); document.addEventListener("mouseleave", handleResizeMouseup, false); document.addEventListener("mouseup", handleResizeMouseup, false); }); // Intercepting all href clicks in TOC that have rel=host toc.addEventListener("click", function (e) { const { target } = e; const { dataset } = target; if (dataset && dataset?.tocAction) { if (dataset.tocAction === "collapse") tocCollapse(target, dataset); } const link = target instanceof HTMLAnchorElement ? target : target.closest("a"); if (link instanceof HTMLAnchorElement && link?.rel === "host") { e.preventDefault(); navigateToPage(link); } }); expander.addEventListener("click", function (e) { e.preventDefault(); expander.style.display = "none"; colapser.style.display = "inline"; allCollapsible.forEach((el) => { el.classList.add("show"); }); allCollapsibleTriggers.forEach((el) => { el.classList.add("expanded"); }); }); colapser.addEventListener("click", function (e) { e.preventDefault(); colapser.style.display = "none"; expander.style.display = "inline"; allCollapsible.forEach((el) => { el.classList.remove("show"); }); allCollapsibleTriggers.forEach((el) => { el.classList.remove("expanded"); }); }); autoSidebarSize(); expandIdentificationSection(); emitMeta(); window.addEventListener("resize", autoSidebarSize); // mapping events to dispatcher & actions const eventMapHandler = { MFEindex: { newDocumentKey: (data) => { if (!data.newDocumentKey) return; // updateDocument(data.newDocumentKey); setActiveLeaf(docKey); }, initConfig: (config) => { if (!config) return; const { documentKey, baseUrl, staticUrl } = config; if (staticUrl) { DAS.staticUrl = staticUrl; } if (baseUrl) { DAS.baseUrl = baseUrl; setBaseHref(baseUrl); } if (documentKey) { // check if document key refers to an existing document const testDocExists = DAS.staticUrl + "documents/" + normalizeKey(documentKey) + ".html"; fetch(testDocExists) .then((r) => { if (r.status === 200) { updateDocument(documentKey); } else { redirectToHeaderDoc(documentKey); } }) .catch((e) => { redirectToHeaderDoc(documentKey); }); } else { visitHeaderDoc(); } }, }, docIframe: { domReady: () => { if (!DAS.baseUrl) return; setDocumentBaseHref(DAS.baseUrl); }, setActiveLeaf: (data) => { if (!data?.documentKey) return; setActiveLeafByDocID(data.documentKey); }, visitDocument: (data) => { const { documentKey, url } = data; updateDocument(documentKey); // notify MFE to use routeCallbackFn const message = { type: "dossierIF.navigate", detail: { href: url, }, }; window.parent.postMessage(message, "*"); }, recalculateDocHeight: () => { setIframeHeight(document.getElementById("pageView")); }, }, }; window.addEventListener("message", (event) => { const { data, origin } = event; // TODO: check origin to whitelist allowed domains const { detail, type } = data; if (typeof type !== "string") return; const [dispatcher, eventType] = type.split("."); const action = eventMapHandler?.[dispatcher]?.[eventType]; if (action && typeof action === "function") { action(detail); } }); // window.addEventListener("message", (event) => { // // }) // if not rendered as iframe, there will be no message so call visitHeaderDoc in setTimeout // to allow body onload to trigger first if (window.self === window.top) { setTimeout(() => visitHeaderDoc()); } initTooltips(); } function expandIdentificationSection() { const s1 = document.getElementById("id_1_Generalinformation"); if (s1) { const b1 = document.querySelector( "[data-toc-target='#id_1_Generalinformation']" ); if (b1) b1.classList.add("expanded"); s1.classList.add("show"); const s2 = document.getElementById("id_11_Identification"); if (s2) { const b2 = document.querySelector( "[data-toc-target='#id_11_Identification']" ); if (b2) b2.classList.add("expanded"); s2.classList.add("show"); const s3 = document.getElementById("id_Identification"); if (s3) { const b3 = document.querySelector( "[data-toc-target='#id_Identification']" ); if (b3) b3.classList.add("expanded"); s3.classList.add("show"); } } } } function updateDocument(docKey) { DAS.documentLoaded = true; const docIframe = document.getElementById("pageView"); docIframe.src = DAS.staticUrl + "documents/" + normalizeKey(docKey) + ".html"; setActiveLeaf(docKey); setTimeout(() => { setIframeHeight(docIframe); }, 1000); } function setBaseHref(href, doc = document) { const iHead = doc.querySelector("head"); const oldBase = doc.querySelector("base"); if (oldBase) oldBase.remove(); const base = doc.createElement("base"); base.setAttribute("href", href); iHead.appendChild(base); } function setDocumentBaseHref(href) { const doc = document.querySelector("iframe").contentDocument; setBaseHref(href, doc); } function tocCollapse(el, dataset) { if (!el || !dataset.tocTarget) return; el.classList.toggle("expanded"); const tocTarget = el.parentNode.parentNode.querySelector(dataset.tocTarget); tocTarget.classList.toggle("show"); const isOpen = tocTarget.classList.contains("show"); // initialize ref docs on first collapse if (!tocTarget.classList.contains("das-refs-checked")) { tocTarget.classList.add("das-refs-checked"); const refsData = tocTarget.dataset["refdocs"]; if (refsData) { const refs = JSON.parse(tocTarget.dataset["refdocs"]); addRefDocsToLinks(refs, tocTarget.querySelector("ul")); } } } function addRefDocsToLinks(refIds, target) { if (refIds && target) { Promise.all(refIds.filter((id) => !!id).map(getTocNode)).then( (refsJson) => { target.innerHTML = createRefDocsHtml(refsJson); const ttTargets = target.querySelectorAll(`.das-has-tooltip`); if (ttTargets?.length > 0) applyTooltips(ttTargets); } ); } } function createRefDocsHtml(refs) { if (!refs || refs.length === 0) return ""; let html = refs?.reduce((html, ref) => { if (!ref || !ref.id) return html; html = html + `
  • ${createRefToggle(ref.refDocs, ref)} ${createRefCollapse(ref?.refDocs, ref)}
  • `; return html; }, ""); return html; } function createRefToggle(refs, parent) { if (!refs || !(refs.length > 0) || !parent) return ""; return ``; } function createRefCollapse(refs, parent) { if (!refs || !(refs.length > 0) || !parent) return ""; return `
    `; } function navigateToPage(link) { setActiveLeaf(link); const identifier = link.getAttribute("href").trim(); const fullUrl = link.href.trim(); document.getElementById("pageView").src = DAS.staticUrl + "documents/" + identifier + ".html"; setTimeout(() => { setIframeHeight(document.getElementById("pageView")); }, 1000); // notify MFE to use routeCallbackFn const message = { type: "dossierIF.navigate", detail: { href: fullUrl, }, }; window.parent.postMessage(message, "*"); } function visitHeaderDoc() { if (!DAS.docUUID || DAS.documentLoaded) return; DAS.documentLoaded = true; const docIframe = document.getElementById("pageView"); docIframe.src = DAS.staticUrl + "documents/" + DAS.docUUID + ".html"; // this is a redirect, so we need to replaceState const message = { type: "dossierIF.replaceState", detail: { href: DAS.baseUrl + DAS.docUUID, }, }; window.parent.postMessage(message, "*"); } function redirectToHeaderDoc(notFoundDocUUID) { const message = { type: "dossierIF.docIdNotFound", detail: { notFoundUUID: notFoundDocUUID, }, }; window.parent.postMessage(message, "*"); visitHeaderDoc(); } function setHeaderDocId(docUUID) { DAS.docUUID = normalizeKey(docUUID); } function setActiveLeaf(el) { if (!el) return; const activeLeaf = typeof el === "string" ? document.querySelector(`[href="${el}"]`) : el; if (!activeLeaf) return; const leafs = document.querySelectorAll(".leaf-active"); leafs.forEach((leaf) => leaf.classList.remove("leaf-active")); activeLeaf.classList.add("leaf-active"); } function toggleSidebar() { document .querySelector(".das-dossier-container") .classList.toggle("collapsed"); } function setActiveLeafByDocID(docId) { if (!docId) return; const currentActiveLeaf = document.querySelector(".leaf-active"); let found = false; if (currentActiveLeaf && currentActiveLeaf.parentNode) { const childContainer = currentActiveLeaf.parentNode.querySelector( ".das-nav_reference_list" ); if (childContainer) { const childRef = childContainer.querySelector(`.das-docid-${docId}`); if (childRef) { found = true; setActiveLeaf(childRef); } } } if (!found) { const childRef = document.querySelector(`.das-docid-${docId}`); if (childRef) setActiveLeaf(childRef); } } function normalizeKey(key) { return key.trim().replace("/", "_"); } function showTooltip(instance, tooltip, tooltipContent, text) { return () => { tooltipContent.innerText = text; tooltip.setAttribute("data-show", ""); instance.setOptions((options) => ({ ...options, modifiers: [ ...options.modifiers, { name: "eventListeners", enabled: true }, ], })); instance.update(); }; } function hideTooltip(instance, tooltip) { return () => { tooltip.removeAttribute("data-show"); instance.setOptions((options) => ({ ...options, modifiers: [ ...options.modifiers, { name: "eventListeners", enabled: false }, ], })); }; } function initTooltips() { if (!DAS.tooltipElement || !DAS.tooltipContent) return; const elementsWithTooltips = document.querySelectorAll(".das-has-tooltip"); applyTooltips(elementsWithTooltips); } function applyTooltips(elements) { if (!DAS.tooltipElement || !DAS.tooltipContent) return; requestIdleCallback(() => { elements.forEach((el, i) => { if (i >= DAS.MAX_TT) { if (i === DAS.MAX_TT) { console.error( "Tooltip max elements exceeded, not applying all tooltips." ); } return; } const tooltipText = el.dataset?.dastttxt; if (tooltipText) { const popperInstance = Popper.createPopper(el, DAS.tooltipElement, { placement: "bottom", modifiers: [ { name: "offset", options: { offset: [0, 8], }, }, ], }); el.addEventListener( "mouseenter", showTooltip( popperInstance, DAS.tooltipElement, DAS.tooltipContent, tooltipText ) ); el.addEventListener( "mouseleave", hideTooltip(popperInstance, DAS.tooltipElement) ); } }); }); } function getTocNode(id) { return fetch(`${DAS.dossierURL}toc/${id}.json`) .then((res) => { try { const data = res.json(); return data; } catch (e) { console.error(`Error parsing json data for ${id}: `, e); return {}; } }) .catch((e) => { console.error(`Error fetching json file for ${id}: `, e); return {}; }); } function handleResizeMouseup() { if (DAS.resizeCfg.tracking) { DAS.resizeCfg.handleOverflow.style.width = "0"; DAS.resizeCfg.tracking = false; } document.removeEventListener("mousemove", handleResizeMousemove, false); document.removeEventListener("mouseleave", handleResizeMouseup, false); document.removeEventListener("mouseup", handleResizeMouseup, false); } function handleResizeMousemove(event) { if (DAS.resizeCfg.tracking) { const cursorScreenXDelta = event.screenX - DAS.resizeCfg.startCursorScreenX; const newWidth = Math.max( DAS.resizeCfg.startWidth + cursorScreenXDelta, DAS.resizeCfg.minWidth ); DAS.resizeCfg.resizeTarget.style.width = `${newWidth}px`; } } function autoSidebarSize() { const el = document.querySelector(".das-dossier-container"); if (window.innerWidth < 1200) { el.classList.add("collapsed"); } else { el.classList.remove("collapsed"); } } function emitMeta() { try { fetch("meta.json") .then((res) => res.json()) .then((meta) => { metaMessage(meta); }); } catch { console.info("MFE meta not available"); } } function metaMessage(meta) { window.parent.postMessage( { type: "dossierIF.mfeMeta", detail: { ...meta, }, }, "*" ); } function setIframeHeight(iFrame, selector = "iframe") { const dossierHeight = document.body.scrollHeight; const docHeight = iFrame.contentDocument.body.scrollHeight + calcLargeTextElementsHeight(iFrame) + iFrame.contentDocument.body.scrollHeight / 2; const appliedHeight = Math.max(dossierHeight, docHeight) + "px"; const printCss = `${selector} { height: ${appliedHeight} !important;}`; const cssSheet = new CSSStyleSheet(); cssSheet.media = "print"; cssSheet.replaceSync(printCss); document.adoptedStyleSheets.push(cssSheet); // if rendered as iframe, parent should also be notified // of the new height of THIS document setTimeout(() => { const message = { type: "dossierIF.setPrintHeight", detail: { height: appliedHeight, }, }; window.parent.postMessage(message, "*"); }, 200); } function calcLargeTextElementsHeight(iframe) { // calculate real height of elements with inner scroll let extraHeight = 0; const classSelector = ".das-field_value_html, .das-field_value_large, .das-value_remark-text"; const els = iframe.querySelectorAll(classSelector); els.forEach((el) => { if (el.scrollHeight > el.clientHeight) { extraHeight = extraHeight + (el.scrollHeight - el.clientHeight); } }); return extraHeight; }