/* global require */ import {initialize} from './components/initialize'; // The Adapter is required when transpiling classes to ES5 code. // https://github.com/webcomponents/webcomponentsjs/tree/v2.2.7#custom-elements-es5-adapterjs import '@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js'; // Webcomponent polyfil window.WebComponents = window.WebComponents || {}; window.WebComponents.root = require( '../../node_modules/@webcomponents/webcomponentsjs/'); function loadFont(src) { const lnk = document.createElement('link'); lnk.setAttribute('href', src); lnk.setAttribute('rel', 'stylesheet'); lnk.setAttribute('type', 'text/css'); document.head.appendChild(lnk); } // https://stackoverflow.com/questions/54546007/why-doesnt-font-awesome-work-in-my-shadow-dom loadFont('https://fonts.googleapis.com/css?family=Roboto:300,400,500,700'); loadFont('https://fonts.googleapis.com/icon?family=Material+Icons'); loadFont('https://use.fontawesome.com/releases/v5.4.1/css/all.css'); class FlowMatic extends HTMLElement { constructor() { super(); } loadComponent() { const oReq = new XMLHttpRequest(); oReq.addEventListener('load', (r) => { const template = document.createElement('template'); template.innerHTML = oReq.responseText; this.attachShadow({mode: 'open'}). appendChild(template.content); this.loadScripts(this.shadowRoot) .then(() => { initialize(this.shadowRoot, true); }); const event = new CustomEvent('flow-matic-loaded', { bubbles: true }); this.dispatchEvent(event); }); oReq.open('GET', `${this.dataset.comp}`); oReq.send(); } static get observedAttributes() { // A list of attribute names to observe via attributeChangedCallback. return ['data-comp']; } attributeChangedCallback() { if (this.dataset.comp) { this.loadComponent(); } } // Scripts that are part of the response and stuck into a template with innerHTML // won't be parsed. On top of that js from a plugin that has a remote dependency // was being parsed before the remote script was loaded (everything was treated async). // This function collects a promise for each remote script and once they're all loaded // it adds the inline scripts. loadScripts(root) { if (window.FLOW_MATIC_SCRIPTS_LOADED) { return Promise.resolve(); } else { window.FLOW_MATIC_SCRIPTS_LOADED = true; } const scripts = Array.from(root.querySelectorAll('script')); const remoteScripts = scripts.filter((s) => { return s.hasAttribute('src'); }); const inlineScripts = scripts.filter((s) => { return !remoteScripts.includes(s); }); // load remote scripts const remoteScriptPromises = remoteScripts.map((script) => { return new Promise((resolve) => { const newScript = this.loadScript(script); newScript.addEventListener('load', () => { resolve(); }); }); }); // When all remote scripts are done, load inlines return Promise.all(remoteScriptPromises).then(() => { inlineScripts.forEach(this.loadScript); }); } // Browsers don't evaluate