UNPKG

@nuxeo/nuxeo-ui-elements

Version:
118 lines (114 loc) 4.32 kB
/** @license Copyright (c) 2017 The Polymer Project Authors. All rights reserved. This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as part of the polymer project is also subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt */ // run a callback when HTMLImports are ready or immediately if // this api is not available. function whenImportsReady(cb) { if (window.HTMLImports) { HTMLImports.whenReady(cb); } else { cb(); } } /** * Convenience method for importing an HTML document imperatively. * * This method creates a new `<link rel="import">` element with * the provided URL and appends it to the document to start loading. * In the `onload` callback, the `import` property of the `link` * element will contain the imported document contents. * * @param {string} href URL to document to load. * @param {?function(!Event):void=} onload Callback to notify when an import successfully * loaded. * @param {?function(!ErrorEvent):void=} onerror Callback to notify when an import * unsuccessfully loaded. * @param {boolean=} optAsync True if the import should be loaded `async`. * Defaults to `false`. * @return {!HTMLLinkElement} The link element for the URL to be loaded. */ export const importHref = function(href, onload, onerror, optAsync) { let link = /** @type {HTMLLinkElement} */ (document.head.querySelector('link[href="' + href + '"][import-href]')); if (!link) { link = /** @type {HTMLLinkElement} */ (document.createElement('link')); link.rel = 'import'; link.href = href; link.setAttribute('import-href', ''); } // always ensure link has `async` attribute if user specified one, // even if it was previously not async. This is considered less confusing. if (optAsync) { link.setAttribute('async', ''); } // NOTE: the link may now be in 3 states: (1) pending insertion, // (2) inflight, (3) already loaded. In each case, we need to add // event listeners to process callbacks. let cleanup = function() { link.removeEventListener('load', loadListener); link.removeEventListener('error', errorListener); }; let loadListener = function(event) { cleanup(); // In case of a successful load, cache the load event on the link so // that it can be used to short-circuit this method in the future when // it is called with the same href param. link.__dynamicImportLoaded = true; if (onload) { whenImportsReady(() => { onload(event); }); } }; let errorListener = function(event) { cleanup(); // In case of an error, remove the link from the document so that it // will be automatically created again the next time `importHref` is // called. if (link.parentNode) { link.parentNode.removeChild(link); } if (onerror) { whenImportsReady(() => { onerror(event); }); } }; link.addEventListener('load', loadListener); link.addEventListener('error', errorListener); if (link.parentNode == null) { document.head.appendChild(link); // if the link already loaded, dispatch a fake load event // so that listeners are called and get a proper event argument. } else if (link.__dynamicImportLoaded) { link.dispatchEvent(new Event('load')); } return link; }; /** * Convenience method for importing inline HTML. * * This method imports all the elements to the document's head * and inlines all the scripts to allow fot their execution. * * @param {string} html HTML to import. */ export const importHTML = (html) => { const tmpl = document.createElement('template'); tmpl.innerHTML = html; [...tmpl.content.children].forEach((el) => { if (el.tagName === 'SCRIPT' && !el.src) { const script = document.createElement('script'); [...el.attributes].forEach((attr) => script.setAttribute(attr.name, attr.value)); script.setAttribute('src', `data:text/javascript;charset=utf-8,${encodeURIComponent(el.textContent)}`); el = script; } document.head.appendChild(el); }); };