Wait for stylesheets to load before setting field content

This commit is contained in:
Henrik Giesel 2021-08-07 01:02:57 +02:00
parent ea01183bfd
commit 701f260c3f
2 changed files with 54 additions and 21 deletions

View file

@ -5,10 +5,41 @@
@typescript-eslint/no-non-null-assertion: "off", @typescript-eslint/no-non-null-assertion: "off",
*/ */
function loadStyleLink(container: Node, href: string): Promise<void> {
const rootStyle = document.createElement("link");
rootStyle.setAttribute("rel", "stylesheet");
rootStyle.setAttribute("href", href);
let styleResolve: () => void;
const stylePromise = new Promise<void>((resolve) => (styleResolve = resolve));
rootStyle.addEventListener("load", () => styleResolve());
container.appendChild(rootStyle);
return stylePromise;
}
function loadStyleTag(container: Node): [HTMLStyleElement, Promise<void>] {
const style = document.createElement("style");
style.setAttribute("rel", "stylesheet");
let styleResolve: () => void;
const stylePromise = new Promise<void>((resolve) => (styleResolve = resolve));
style.addEventListener("load", () => styleResolve());
container.appendChild(style);
return [style, stylePromise];
}
export class EditableContainer extends HTMLDivElement { export class EditableContainer extends HTMLDivElement {
baseStyle: HTMLStyleElement; baseStyle: HTMLStyleElement;
imageStyle: HTMLStyleElement;
imagePromise: Promise<void>;
stylePromise: Promise<void>;
baseRule?: CSSStyleRule; baseRule?: CSSStyleRule;
imageStyle?: HTMLStyleElement;
constructor() { constructor() {
super(); super();
@ -18,15 +49,19 @@ export class EditableContainer extends HTMLDivElement {
this.classList.add("night-mode"); this.classList.add("night-mode");
} }
const rootStyle = document.createElement("link"); const rootPromise = loadStyleLink(shadow, "./_anki/css/editable-build.css");
rootStyle.setAttribute("rel", "stylesheet"); const [baseStyle, basePromise] = loadStyleTag(shadow);
rootStyle.setAttribute("href", "./_anki/css/editable-build.css"); const [imageStyle, imagePromise] = loadStyleTag(shadow);
shadow.appendChild(rootStyle);
this.baseStyle = document.createElement("style"); this.baseStyle = baseStyle;
this.baseStyle.setAttribute("rel", "stylesheet"); this.imageStyle = imageStyle;
this.baseStyle.id = "baseStyle";
shadow.appendChild(this.baseStyle); this.imagePromise = imagePromise;
this.stylePromise = Promise.all([
rootPromise,
basePromise,
imagePromise,
]) as unknown as Promise<void>;
} }
connectedCallback(): void { connectedCallback(): void {

View file

@ -39,12 +39,7 @@ export class EditingArea extends HTMLDivElement {
is: "anki-editable-container", is: "anki-editable-container",
}) as EditableContainer; }) as EditableContainer;
const imageStyle = document.createElement("style");
imageStyle.setAttribute("rel", "stylesheet");
imageStyle.id = "imageHandleStyle";
this.editable = document.createElement("anki-editable") as Editable; this.editable = document.createElement("anki-editable") as Editable;
this.editableContainer.shadowRoot!.appendChild(imageStyle);
this.editableContainer.shadowRoot!.appendChild(this.editable); this.editableContainer.shadowRoot!.appendChild(this.editable);
this.appendChild(this.editableContainer); this.appendChild(this.editableContainer);
@ -55,18 +50,18 @@ export class EditingArea extends HTMLDivElement {
); );
let imageHandleResolve: (value: ImageHandle) => void; let imageHandleResolve: (value: ImageHandle) => void;
this.imageHandle = new Promise<ImageHandle>((resolve) => { this.imageHandle = new Promise<ImageHandle>(
imageHandleResolve = resolve; (resolve) => (imageHandleResolve = resolve)
}); );
imageStyle.addEventListener("load", () => this.editableContainer.imagePromise.then(() =>
imageHandleResolve( imageHandleResolve(
new ImageHandle({ new ImageHandle({
target: this, target: this,
anchor: this.editableContainer, anchor: this.editableContainer,
props: { props: {
container: this.editable, container: this.editable,
sheet: imageStyle.sheet, sheet: this.editableContainer.imageStyle.sheet,
}, },
context, context,
} as any) } as any)
@ -105,6 +100,7 @@ export class EditingArea extends HTMLDivElement {
set fieldHTML(content: string) { set fieldHTML(content: string) {
this.imageHandle.then(() => { this.imageHandle.then(() => {
let result = content; let result = content;
for (const component of decoratedComponents) { for (const component of decoratedComponents) {
result = component.toUndecorated(result); result = component.toUndecorated(result);
} }
@ -149,8 +145,10 @@ export class EditingArea extends HTMLDivElement {
} }
initialize(color: string, content: string): void { initialize(color: string, content: string): void {
this.setBaseColor(color); this.editableContainer.stylePromise.then(() => {
this.fieldHTML = content; this.setBaseColor(color);
this.fieldHTML = content;
});
} }
setBaseColor(color: string): void { setBaseColor(color: string): void {