@nent/core
Version:
295 lines (294 loc) • 8.3 kB
JavaScript
/*!
* NENT 2022
*/
import { Component, Element, Event, Method, Prop, } from '@stencil/core';
import { warn } from '../../services/common/logging';
import { hasReference, markReference, ReferenceType, } from '../../services/content';
/**
* This element makes a single reference to script and css sources. It can
* be used by HTML fragment to ensure a reference is made, without worrying
* that it will create duplicate references.
*
* @system content
*/
export class ContentReference {
constructor() {
/**
* Import the script file as a module.
*/
this.module = false;
/**
* Declare the script only for use when
* modules aren't supported
*/
this.noModule = false;
/**
* When inline the link/script tags are rendered in-place
* rather than added to the head.
*/
this.inline = false;
/**
* If set, disables auto-rendering of this instance.
* To fetch the contents change to false or remove
* attribute.
*/
this.deferLoad = false;
/**
* Timeout (in milliseconds) to wait for the references
* to load.
*/
this.timeout = 1000;
}
/**
* Force the 'load' event of the script or link element.
* This is meant for testing.
*
*/
async forceLoad() {
var _a, _b;
(_a = this.scriptElement) === null || _a === void 0 ? void 0 : _a.dispatchEvent(new CustomEvent('load'));
(_b = this.linkElement) === null || _b === void 0 ? void 0 : _b.dispatchEvent(new CustomEvent('load'));
}
registered(type, loaded) {
this.reference.emit({ type, loaded });
}
async getStylePromise(element) {
const url = this.styleSrc;
return new Promise(async (resolve) => {
if (url == undefined) {
return resolve(false);
}
const reffed = await hasReference(url);
if (reffed) {
return resolve(true);
}
this.linkElement = this.el.ownerDocument.createElement('link');
this.linkElement.href = url;
this.linkElement.rel = 'stylesheet';
let loaded = false;
this.linkElement.addEventListener('load', async () => {
loaded = true;
return resolve(loaded);
});
element.append(this.linkElement);
await markReference(url);
setTimeout(() => {
if (!loaded) {
warn(`Stylesheet '${url}' did not load before the ${this.timeout} timeout.`);
resolve(false);
}
}, this.timeout);
});
}
getScriptPromise(element) {
const url = this.scriptSrc;
return new Promise(async (resolve) => {
if (url == undefined) {
return resolve(false);
}
const reffed = await hasReference(url);
if (reffed) {
return resolve(true);
}
this.scriptElement =
this.el.ownerDocument.createElement('script');
this.scriptElement.src = url;
let loaded = false;
if (this.module) {
this.scriptElement.type = 'module';
}
else if (this.noModule) {
this.scriptElement.setAttribute('nomodule', '');
}
this.scriptElement.addEventListener('load', async () => {
loaded = true;
await markReference(url);
return resolve(loaded);
});
element.append(this.scriptElement);
await markReference(url);
setTimeout(() => {
if (!loaded) {
warn(`Script '${url}' did not load before the ${this.timeout} timeout.`);
resolve(false);
}
}, this.timeout);
});
}
async componentWillRender() {
if (this.deferLoad) {
return;
}
const element = this.inline ? this.el : this.el.ownerDocument.head;
await this.getStylePromise(element).then(loaded => this.registered(ReferenceType.styles, loaded));
await this.getScriptPromise(element).then(loaded => this.registered(ReferenceType.script, loaded));
}
disconnectedCallback() { }
static get is() { return "n-content-reference"; }
static get properties() { return {
"styleSrc": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "The css file to reference"
},
"attribute": "style-src",
"reflect": false
},
"scriptSrc": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "The script file to reference."
},
"attribute": "script-src",
"reflect": false
},
"module": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Import the script file as a module."
},
"attribute": "module",
"reflect": false,
"defaultValue": "false"
},
"noModule": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Declare the script only for use when\nmodules aren't supported"
},
"attribute": "no-module",
"reflect": false,
"defaultValue": "false"
},
"inline": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "When inline the link/script tags are rendered in-place\nrather than added to the head."
},
"attribute": "inline",
"reflect": false,
"defaultValue": "false"
},
"deferLoad": {
"type": "boolean",
"mutable": true,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "If set, disables auto-rendering of this instance.\nTo fetch the contents change to false or remove\nattribute."
},
"attribute": "defer-load",
"reflect": false,
"defaultValue": "false"
},
"timeout": {
"type": "number",
"mutable": false,
"complexType": {
"original": "number",
"resolved": "number",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Timeout (in milliseconds) to wait for the references\nto load."
},
"attribute": "timeout",
"reflect": false,
"defaultValue": "1000"
}
}; }
static get events() { return [{
"method": "reference",
"name": "referenced",
"bubbles": true,
"cancelable": false,
"composed": true,
"docs": {
"tags": [],
"text": "This event is fired when the script and style\nelements are loaded or timed out. The value for each\nstyle and script will be true or false, for loaded\nor timedout, respectively."
},
"complexType": {
"original": "ReferenceCompleteResults",
"resolved": "{ type: ReferenceType; loaded: boolean; }",
"references": {
"ReferenceCompleteResults": {
"location": "import",
"path": "../../services/content"
}
}
}
}]; }
static get methods() { return {
"forceLoad": {
"complexType": {
"signature": "() => Promise<void>",
"parameters": [],
"references": {
"Promise": {
"location": "global"
}
},
"return": "Promise<void>"
},
"docs": {
"text": "Force the 'load' event of the script or link element.\nThis is meant for testing.",
"tags": []
}
}
}; }
static get elementRef() { return "el"; }
}