mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00

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.
51 lines
1.6 KiB
TypeScript
51 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"));
|
|
}
|
|
}
|