779ca57660
* Refactor CSS preloading - Rename css.ts to preload.ts - Rename type/function names - Automatically remove style/link element on load/error event * Refactor image preloading - Reuse template element - Change timeout value from 100ms to 200ms, as it often takes more than 100ms to load even a single small image on a low-spec machine - Refactor preloadAnswerImages(): - Use 'new Image()' instead of <link rel=preload> - Stop calculating images that only appear on the answer side as cached images are resolved immediately * Update tsconfig.json es2020.string -> String.matchAll() es2018.regexp -> RegExprMatchArray.groups * Implement custom font preloading Font files for some languages such as Chinese and Japanese can be as large as 20MB, so we set the timeout value to 800ms for font preloading.
43 lines
1.3 KiB
TypeScript
43 lines
1.3 KiB
TypeScript
// Copyright: Ankitects Pty Ltd and contributors
|
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
|
|
const template = document.createElement("template");
|
|
|
|
export function allImagesLoaded(): Promise<void[]> {
|
|
return Promise.all(
|
|
Array.from(document.getElementsByTagName("img")).map(imageLoaded),
|
|
);
|
|
}
|
|
|
|
function imageLoaded(img: HTMLImageElement): Promise<void> {
|
|
return img.complete
|
|
? Promise.resolve()
|
|
: new Promise((resolve) => {
|
|
img.addEventListener("load", () => resolve());
|
|
img.addEventListener("error", () => resolve());
|
|
});
|
|
}
|
|
|
|
function extractImageSrcs(fragment: DocumentFragment): string[] {
|
|
const srcs = [...fragment.querySelectorAll("img[src]")].map(
|
|
(img) => (img as HTMLImageElement).src,
|
|
);
|
|
return srcs;
|
|
}
|
|
|
|
function createImage(src: string): HTMLImageElement {
|
|
const img = new Image();
|
|
img.src = src;
|
|
return img;
|
|
}
|
|
|
|
export function preloadAnswerImages(html: string): void {
|
|
template.innerHTML = html;
|
|
extractImageSrcs(template.content).forEach(createImage);
|
|
}
|
|
|
|
/** Prevent flickering & layout shift on image load */
|
|
export function preloadImages(fragment: DocumentFragment): Promise<void>[] {
|
|
return extractImageSrcs(fragment).map(createImage).map(imageLoaded);
|
|
}
|