From e131b70c4c08aa0038602a3707d5d088965b6684 Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Tue, 13 Apr 2021 00:22:00 +0200 Subject: [PATCH 1/5] Remove jQuery from _updateQA --- qt/aqt/data/web/js/reviewer.ts | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/qt/aqt/data/web/js/reviewer.ts b/qt/aqt/data/web/js/reviewer.ts index fb197df79..2f8d896f5 100644 --- a/qt/aqt/data/web/js/reviewer.ts +++ b/qt/aqt/data/web/js/reviewer.ts @@ -9,9 +9,6 @@ var ankiPlatform = "desktop"; var typeans; var _updatingQueue: Promise = Promise.resolve(); -var qFade = 0; -var aFade = 0; - var onUpdateHook: Array; var onShownHook: Array; @@ -31,32 +28,25 @@ function _queueAction(action: Callback): void { async function _updateQA( html: string, - fadeTime: number, 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); + qa.innerHTML = html; } catch (error) { renderError("HTML")(error); } @@ -69,15 +59,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 +75,6 @@ function _showQuestion(q: string, bodyclass: string): void { _queueAction(() => _updateQA( q, - qFade, function () { // return to top of window window.scrollTo(0, 0); @@ -107,7 +96,6 @@ function _showAnswer(a: string, bodyclass: string): void { _queueAction(() => _updateQA( a, - aFade, function () { if (bodyclass) { // when previewing From f4f0298378396057fa1fa6291796d0bfaffa99ad Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Tue, 13 Apr 2021 00:37:58 +0200 Subject: [PATCH 2/5] Remove jQuery from mark and flag in reviewer.ts --- qt/aqt/data/web/js/reviewer.ts | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/qt/aqt/data/web/js/reviewer.ts b/qt/aqt/data/web/js/reviewer.ts index 2f8d896f5..72e1b1043 100644 --- a/qt/aqt/data/web/js/reviewer.ts +++ b/qt/aqt/data/web/js/reviewer.ts @@ -6,7 +6,7 @@ declare var MathJax: any; type Callback = () => void | Promise; var ankiPlatform = "desktop"; -var typeans; +var typeans: HTMLElement | undefined; var _updatingQueue: Promise = Promise.resolve(); var onUpdateHook: Array; @@ -38,7 +38,10 @@ async function _updateQA( const renderError = (kind: string) => (error: Error): void => { const errorMessage = String(error).substring(0, 2000); const errorStack = String(error.stack).substring(0, 2000); - qa.innerHTML = `Invalid ${kind} on card: ${errorMessage}\n${errorStack}`.replace(/\n/g, "
"); + qa.innerHTML = `Invalid ${kind} on card: ${errorMessage}\n${errorStack}`.replace( + /\n/g, + "
" + ); }; // hide current card @@ -119,26 +122,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"); } } From 74a9d0b0a159f0bcac1c8177feaede617481a505 Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Tue, 13 Apr 2021 00:42:09 +0200 Subject: [PATCH 3/5] Make imageLoaded adhere to its function signature --- qt/aqt/data/web/js/reviewer.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/qt/aqt/data/web/js/reviewer.ts b/qt/aqt/data/web/js/reviewer.ts index 72e1b1043..e41144780 100644 --- a/qt/aqt/data/web/js/reviewer.ts +++ b/qt/aqt/data/web/js/reviewer.ts @@ -162,13 +162,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 { From c9fcf955f43d2b1f329c4069156ef1bfbaab3ce2 Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Tue, 13 Apr 2021 01:00:09 +0200 Subject: [PATCH 4/5] Remove display:none from mark and flag, and preset hidden attribute instead --- qt/aqt/data/web/css/reviewer.scss | 2 -- qt/aqt/reviewer.py | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) 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/reviewer.py b/qt/aqt/reviewer.py index 0394bc8fd..1248c3755 100644 --- a/qt/aqt/reviewer.py +++ b/qt/aqt/reviewer.py @@ -183,10 +183,10 @@ class Reviewer: if self.mw.pm.video_driver() == VideoDriver.Software: fade = "" return f""" -
-
+ + {fade} -
+
{extra} """ From be7630648d5dd9668199e06f21bdc8213abd5638 Mon Sep 17 00:00:00 2001 From: Henrik Giesel Date: Tue, 13 Apr 2021 13:32:50 +0200 Subject: [PATCH 5/5] Add setInnerHTML as a Replacement for $.html --- qt/aqt/data/web/js/reviewer.ts | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/qt/aqt/data/web/js/reviewer.ts b/qt/aqt/data/web/js/reviewer.ts index e41144780..fe9935e87 100644 --- a/qt/aqt/data/web/js/reviewer.ts +++ b/qt/aqt/data/web/js/reviewer.ts @@ -26,8 +26,34 @@ 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, + _unusused: unknown, onupdate: Callback, onshown: Callback ): Promise { @@ -49,7 +75,7 @@ async function _updateQA( // update card try { - qa.innerHTML = html; + setInnerHTML(qa, html); } catch (error) { renderError("HTML")(error); } @@ -78,6 +104,7 @@ function _showQuestion(q: string, bodyclass: string): void { _queueAction(() => _updateQA( q, + null, function () { // return to top of window window.scrollTo(0, 0); @@ -99,6 +126,7 @@ function _showAnswer(a: string, bodyclass: string): void { _queueAction(() => _updateQA( a, + null, function () { if (bodyclass) { // when previewing