207e4253f1
https://forums.ankiweb.net/t/audio-in-back-template-is-played-on-front-template-on-desktop-2-1-46/12399 Unlike when using <template> element, if a DocumentFragment is created using Range.createContextualFragment(), <audio>/<video> elements with `aotoplay` will play immediately even before they are inserted into the actual document, which will cause audio or video on the answer side to be played on the question side.
52 lines
1.6 KiB
TypeScript
52 lines
1.6 KiB
TypeScript
// Copyright: Ankitects Pty Ltd and contributors
|
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
|
|
function injectPreloadLink(href: string, as: string): void {
|
|
const link = document.createElement("link");
|
|
link.rel = "preload";
|
|
link.href = href;
|
|
link.as = as;
|
|
document.head.appendChild(link);
|
|
}
|
|
|
|
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 clearPreloadLinks(): void {
|
|
document.head
|
|
.querySelectorAll("link[rel='preload']")
|
|
.forEach((link) => link.remove());
|
|
}
|
|
|
|
function extractImageSrcs(html: string): string[] {
|
|
const tmpl = document.createElement("template");
|
|
tmpl.innerHTML = html;
|
|
const fragment = tmpl.content;
|
|
const srcs = [...fragment.querySelectorAll("img[src]")].map(
|
|
(img) => (img as HTMLImageElement).src
|
|
);
|
|
return srcs;
|
|
}
|
|
|
|
export function preloadAnswerImages(qHtml: string, aHtml: string): void {
|
|
clearPreloadLinks();
|
|
const aSrcs = extractImageSrcs(aHtml);
|
|
if (aSrcs.length) {
|
|
const qSrcs = extractImageSrcs(qHtml);
|
|
const diff = aSrcs.filter((src) => !qSrcs.includes(src));
|
|
diff.forEach((src) => injectPreloadLink(src, "image"));
|
|
}
|
|
}
|