##// END OF EJS Templates
Added 'Attrs', 'Events' type parameters to DjxWidgetBase, typed 'on' and 'emit' methods
Added 'Attrs', 'Events' type parameters to DjxWidgetBase, typed 'on' and 'emit' methods

File last commit:

r19:8f4d5e2c719a v1.0.0-rc8 default
r30:a46488b209e8 v1.0.0-rc14 default
Show More
dom-inject.ts
96 lines | 2.5 KiB | video/mp2t | TypeScriptLexer
import { id as mid } from "module";
import { TraceSource } from "@implab/core-amd/log/TraceSource";
import { MapOf } from "@implab/core-amd/interfaces";
import { mixin } from "@implab/core-amd/safe";
const trace = TraceSource.get(mid);
function on<T extends keyof HTMLElementEventMap>(node: HTMLElement, eventName: T, handler: (this: HTMLElement, ev: HTMLElementEventMap[T]) => any): () => void {
// Add an event listener to a DOM node
node.addEventListener(eventName, handler, false);
return () => node.removeEventListener(eventName, handler, false);
}
interface NodeLoadResult {
node: HTMLElement;
}
class DomInject {
injectionPoint = document.head;
injectBefore = document.head.firstChild;
_map: MapOf<Promise<NodeLoadResult>> = {};
_inject<T extends keyof HTMLElementTagNameMap>(name: T, attr: Partial<HTMLElementTagNameMap[T]>) {
const node = document.createElement(name);
return new Promise<NodeLoadResult>((ok, fail) => {
const cleanup = () => {
noerr();
noload();
};
const noload = on(node, "load", () => {
ok({ node });
cleanup();
});
const noerr = on(node, "error", e => {
fail({
erorr: e,
node
});
cleanup();
});
mixin(node, attr);
this.injectionPoint.insertBefore(node, this.injectBefore);
});
}
async injectScript(url: string) {
let d = this._map[url];
if (!d) {
trace.log("js {0}", url);
d = this._inject("script", {
type: "text/javascript",
charset: "utf-8",
src: url
});
this._map[url] = d;
}
try {
await d;
trace.log("done {0}", url);
} catch (e) {
trace.error("failed {0}: {1}", url, e);
throw e;
}
}
async injectStylesheet(url: string) {
let d = this._map[url];
if (!d) {
trace.log("js {0}", url);
d = this._inject("link", {
type: "text/css",
rel: "stylesheet",
href: url
});
this._map[url] = d;
}
try {
await d;
trace.log("done {0}", url);
} catch (e) {
trace.error("failed {0}: {1}", url, e);
throw e;
}
}
};
const instance = new DomInject();
export = instance;