lazy-import
Version:
An element based on polymer v2 to lazy import other elements.
143 lines (130 loc) • 5.42 kB
HTML
<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>