diff --git a/qt/aqt/data/web/css/reviewer.scss b/qt/aqt/data/web/css/reviewer.scss index fd04219a7..1e091a220 100644 --- a/qt/aqt/data/web/css/reviewer.scss +++ b/qt/aqt/data/web/css/reviewer.scss @@ -27,7 +27,6 @@ img { right: 10px; top: 0; font-size: 30px; - display: none; -webkit-text-stroke-width: 1px; -webkit-text-stroke-color: black; } @@ -38,7 +37,6 @@ img { top: 0; font-size: 30px; color: yellow; - display: none; -webkit-text-stroke-width: 1px; -webkit-text-stroke-color: black; } diff --git a/qt/aqt/data/web/js/reviewer.ts b/qt/aqt/data/web/js/reviewer.ts index fb197df79..fe9935e87 100644 --- a/qt/aqt/data/web/js/reviewer.ts +++ b/qt/aqt/data/web/js/reviewer.ts @@ -6,12 +6,9 @@ declare var MathJax: any; type Callback = () => void | Promise; var ankiPlatform = "desktop"; -var typeans; +var typeans: HTMLElement | undefined; var _updatingQueue: Promise = Promise.resolve(); -var qFade = 0; -var aFade = 0; - var onUpdateHook: Array; var onShownHook: Array; @@ -29,34 +26,56 @@ function _queueAction(action: Callback): void { _updatingQueue = _updatingQueue.then(action); } +function setInnerHTML(element: Element, html: string): void { + for (const oldVideo of element.getElementsByTagName("video")) { + oldVideo.pause(); + + while (oldVideo.firstChild) { + oldVideo.removeChild(oldVideo.firstChild); + } + + oldVideo.load(); + } + + element.innerHTML = html; + + for (const oldScript of element.getElementsByTagName("script")) { + const newScript = document.createElement("script"); + + for (const attribute of oldScript.attributes) { + newScript.setAttribute(attribute.name, attribute.value); + } + + newScript.appendChild(document.createTextNode(oldScript.innerHTML)); + oldScript.parentNode.replaceChild(newScript, oldScript); + } +} + async function _updateQA( html: string, - fadeTime: number, + _unusused: unknown, onupdate: Callback, onshown: Callback ): Promise { onUpdateHook = [onupdate]; onShownHook = [onshown]; - const qa = $("#qa"); + const qa = document.getElementById("qa")!; const renderError = (kind: string) => (error: Error): void => { const errorMessage = String(error).substring(0, 2000); const errorStack = String(error.stack).substring(0, 2000); - - qa.html( - `Invalid ${kind} on card: ${errorMessage}\n${errorStack}`.replace( - /\n/g, - "
" - ) + qa.innerHTML = `Invalid ${kind} on card: ${errorMessage}\n${errorStack}`.replace( + /\n/g, + "
" ); }; - // fade out current text - await qa.fadeTo(fadeTime, 0).promise(); + // hide current card + qa.style.opacity = "0"; - // update text + // update card try { - qa.html(html); + setInnerHTML(qa, html); } catch (error) { renderError("HTML")(error); } @@ -69,15 +88,15 @@ async function _updateQA( // clear MathJax buffers from previous typesets MathJax.typesetClear(); - return MathJax.typesetPromise(qa.slice(0, 1)); + return MathJax.typesetPromise([qa]); }) .catch(renderError("MathJax")); // defer display for up to 100ms to allow images to load await Promise.race([allImagesLoaded(), new Promise((r) => setTimeout(r, 100))]); - // and reveal when processing is done - await qa.fadeTo(fadeTime, 1).promise(); + // and reveal card when processing is done + qa.style.opacity = "1"; await _runHook(onShownHook); } @@ -85,7 +104,7 @@ function _showQuestion(q: string, bodyclass: string): void { _queueAction(() => _updateQA( q, - qFade, + null, function () { // return to top of window window.scrollTo(0, 0); @@ -107,7 +126,7 @@ function _showAnswer(a: string, bodyclass: string): void { _queueAction(() => _updateQA( a, - aFade, + null, function () { if (bodyclass) { // when previewing @@ -131,26 +150,26 @@ const _flagColours = { }; function _drawFlag(flag: 0 | 1 | 2 | 3 | 4): void { - var elem = $("#_flag"); + const elem = document.getElementById("_flag"); if (flag === 0) { - elem.hide(); + elem.setAttribute("hidden", ""); return; } - elem.show(); - elem.css("color", _flagColours[flag]); + elem.removeAttribute("hidden"); + elem.style.color = _flagColours[flag]; } function _drawMark(mark: boolean): void { - var elem = $("#_mark"); + const elem = document.getElementById("_mark"); if (!mark) { - elem.hide(); + elem.setAttribute("hidden", ""); } else { - elem.show(); + elem.removeAttribute("hidden"); } } function _typeAnsPress(): void { - if ((window.event as KeyboardEvent).keyCode === 13) { + if ((window.event as KeyboardEvent).code === "Enter") { pycmd("ans"); } } @@ -171,13 +190,12 @@ function allImagesLoaded(): Promise { } function imageLoaded(img: HTMLImageElement): Promise { - if (img.complete) { - return; - } - return new Promise((resolve) => { - img.addEventListener("load", () => resolve()); - img.addEventListener("error", () => resolve()); - }); + return img.complete + ? Promise.resolve() + : new Promise((resolve) => { + img.addEventListener("load", () => resolve()); + img.addEventListener("error", () => resolve()); + }); } function scrollToAnswer(): void { diff --git a/qt/aqt/reviewer.py b/qt/aqt/reviewer.py index e7d5cc525..6c054e934 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -184,10 +184,10 @@ class Reviewer: if self.mw.pm.video_driver() == VideoDriver.Software: fade = "" return f""" -
-
+ + {fade} -
+
{extra} """