UNPKG

lazy-import

Version:

An element based on polymer v2 to lazy import other elements.

143 lines (130 loc) 5.42 kB
<link rel="import" href="./bower_components/polymer/polymer-element.html"> <link rel="import" href="./bower_components/polymer/lib/utils/templatize.html"> <link rel="import" href="./bower_components/polymer/lib/utils/debounce.html"> <link rel="import" href="./bower_components/polymer/lib/utils/flush.html"> <link rel="import" href="./bower_components/polymer/lib/utils/import-href.html"> <link rel="import" href="./bower_components/polymer/lib/utils/resolve-url.html"> <script> (function () { 'use strict'; /** * `lazy-import` * An element based on polymer v2 to lazy import other elements. * * @customElement * @polymer * @demo demo/index.html */ class LazyImport extends Polymer.Element { static get is() { return 'lazy-import'; } static get template() { return null; } static get properties() { return { prop1: { type: String, value: 'lazy-import' }, href: { type: String, reflectToAttribute: true } }; } constructor() { super(); this.__renderDebouncer = null; this.__instance = null; this.__ctor = null; } __debounceRender() { this.__renderDebouncer = Polymer.Debouncer.debounce( this.__renderDebouncer, Polymer.Async.microTask, () => this.__render() ); Polymer.enqueueDebouncer(this.__renderDebouncer); } connectedCallback() { super.connectedCallback(); this.style.display = 'none'; Polymer.importHref(Polymer.ResolveUrl.resolveUrl(this.href), () => { this.__debounceRender(); }); } disconnectedCallback() { super.disconnectedCallback(); if (!this.parentNode || (this.parentNode.nodeType == Node.DOCUMENT_FRAGMENT_NODE && !this.parentNode.host)) { this.__teardownInstance(); } } __render() { if (!this.__ensureInstance()) { // No template found yet return; } this.dispatchEvent(new CustomEvent('dom-change', { bubbles: true, composed: true })); } __ensureInstance() { let parentNode = this.parentNode; // Guard against element being detached while render was queued if (parentNode) { let template = this.querySelector('template'); if (!template) { // Wait until childList changes and template should be there by then let observer = new MutationObserver(() => { if (this.querySelector('template')) { observer.disconnect(); this.__render(); } else { throw new Error('lazy-import requires a <template> child'); } }); observer.observe(this, {childList: true}); return false; } this.__ctor = Polymer.Templatize.templatize(template, this, { // dom-if templatizer instances require `mutable: true`, as // `__syncHostProperties` relies on that behavior to sync objects mutableData: true, /** * @param {string} prop Property to forward * @param {*} value Value of property * @this {this} */ forwardHostProp: function (prop, value) { if (this.__instance) { this.__instance.forwardHostProp(prop, value); } } }); this.__instance = new this.__ctor(); parentNode.insertBefore(this.__instance.root, this); } return true; } __teardownInstance() { if (this.__instance) { let c$ = this.__instance.children; if (c$ && c$.length) { // use first child parent, for case when lazy-import may have been detached let parent = c$[0].parentNode; for (let i = 0, n; (i < c$.length) && (n = c$[i]); i++) { parent.removeChild(n); } } this.__instance = null; } } } window.customElements.define(LazyImport.is, LazyImport); })(); </script>