diff --git a/aqt/browser.py b/aqt/browser.py
index 895cf9451..3b3fde034 100644
--- a/aqt/browser.py
+++ b/aqt/browser.py
@@ -1124,7 +1124,7 @@ where id in %s""" % ids2str(sf))
"mathjax/conf.js", "mathjax/MathJax.js",
"mathjax/queue-typeset.js"]
self._previewWeb.stdHtml(
- ti(mungeQA(self.col, txt)), self.mw.reviewer._styles(),
+ ti(mungeQA(self.col, txt))+self._previewWeb.bundledCSS("reviewer.css"),
bodyClass="card card%d" % (c.ord+1), head=base,
js=jsinc)
clearAudioQueue()
diff --git a/aqt/clayout.py b/aqt/clayout.py
index 7e2b9a11b..71614d0c6 100644
--- a/aqt/clayout.py
+++ b/aqt/clayout.py
@@ -230,10 +230,12 @@ Please create a new card type first."""))
self.tab['pform'].frontWeb.setEnabled(False)
self.tab['pform'].backWeb.setEnabled(False)
self.tab['pform'].frontWeb.stdHtml(
- ti(mungeQA(self.mw.col, c.q(reload=True))), self.mw.reviewer._styles(),
+ ti(mungeQA(self.mw.col, c.q(reload=True)))+
+ self.tab['pform'].frontWeb.bundledCSS("reviewer.css"),
bodyClass="card card%d" % (c.ord+1), head=base, js=jsinc),
self.tab['pform'].backWeb.stdHtml(
- ti(mungeQA(self.mw.col, c.a()), type='a'), self.mw.reviewer._styles(),
+ ti(mungeQA(self.mw.col, c.a()), type='a')+
+ self.tab['pform'].backWeb.bundledCSS("reviewer.css"),
bodyClass="card card%d" % (c.ord+1), head=base, js=jsinc),
self.tab['pform'].frontWeb.setEnabled(True)
self.tab['pform'].backWeb.setEnabled(True)
diff --git a/aqt/reviewer.py b/aqt/reviewer.py
index bd4af1d5d..50a933491 100644
--- a/aqt/reviewer.py
+++ b/aqt/reviewer.py
@@ -120,7 +120,8 @@ class Reviewer:
_revHtml = """
-
+
"""
def _initWeb(self):
@@ -129,7 +130,8 @@ class Reviewer:
base = self.mw.baseHTML()
# main window
self.web.onLoadFinished = self._showQuestion
- self.web.stdHtml(self._revHtml, self._styles(), head=base,
+ self.web.stdHtml(self._revHtml +
+ self.web.bundledCSS("reviewer.css"), head=base,
js=["jquery.js",
"browsersel.js",
"mathjax/conf.js",
@@ -159,15 +161,19 @@ class Reviewer:
if c.isEmpty():
q = _("""\
The front of this card is empty. Please run Tools>Empty Cards.""")
+ a = ""
else:
q = c.q()
+ a = c.a()
if self.autoplay(c):
playFromText(q)
# render & update bottom
q = self._mungeQA(q)
- q += self._hiddenUpcomingImages()
- klass = "card card%d" % (c.ord+1)
- self.web.eval("_updateQA(%s, false, '%s');" % (json.dumps(q), klass))
+ a = self._mungeQA(a)
+
+ bodyclass = "card card%d" % (c.ord+1)
+
+ self.web.eval("_showQuestion(%s, %s, '%s');" % (json.dumps(q), json.dumps(a), bodyclass))
self._toggleStar()
if self._bottomReady:
self._showAnswerButton()
@@ -204,8 +210,7 @@ The front of this card is empty. Please run Tools>Empty Cards.""")
if self.autoplay(c):
playFromText(a)
# render and update bottom
- a = self._mungeQA(a)
- self.web.eval("_updateQA(%s, true);" % json.dumps(a))
+ self.web.eval("_showAnswer(%s);" % json.dumps(''))
self._showEaseButtons()
# user hook
runHook('showAnswer')
@@ -227,37 +232,6 @@ The front of this card is empty. Please run Tools>Empty Cards.""")
self.mw.autosave()
self.nextCard()
- # Image preloading
- ##########################################################################
-
- def _hiddenUpcomingImages(self):
- return ""+self._upcomingImages()+"
"
-
- def _upcomingImages(self):
- # grab the top cards in each queue
- s = self.mw.col.sched
- cids = []
- cids.append(s._lrnQueue and s._lrnQueue[0][1])
- cids.append(s._revQueue and s._revQueue[0])
- cids.append(s._newQueue and s._newQueue[0])
-
- # gather their content
- qa = []
- for cid in cids:
- if not cid:
- continue
- c = self.mw.col.getCard(cid)
- qa.append(c.q())
- qa.append(c.a())
-
- # pluck image links out
- qa = "".join(qa)
- links = []
- for regex in self.mw.col.media.imgRegexps:
- links.extend(re.findall(regex, qa))
-
- return "".join([x[0] for x in links])
-
# Handlers
############################################################
@@ -302,23 +276,6 @@ The front of this card is empty. Please run Tools>Empty Cards.""")
else:
print("unrecognized anki link:", url)
- # CSS
- ##########################################################################
-
- _css = """
-hr { background-color:#ccc; margin: 1em; }
-body { margin:1.5em; }
-img { max-width: 95%; max-height: 95%; }
-.marked { position:fixed; right: 7px; top: 7px; display: none; }
-#typeans { width: 100%; }
-.typeGood { background: #0f0; }
-.typeBad { background: #f00; }
-.typeMissed { background: #ccc; }
-"""
-
- def _styles(self):
- return self._css
-
# Type in the answer
##########################################################################
diff --git a/web/reviewer.css b/web/reviewer.css
new file mode 100644
index 000000000..03430b51e
--- /dev/null
+++ b/web/reviewer.css
@@ -0,0 +1,10 @@
+hr { background-color:#ccc; margin: 1em; }
+body { margin:1.5em; }
+img { max-width: 95%; max-height: 95%; }
+.marked { position:fixed; right: 7px; top: 7px; display: none; }
+#typeans { width: 100%; }
+.typeGood { background: #0f0; }
+.typeBad { background: #f00; }
+.typeMissed { background: #ccc; }
+#qa { position: relative; }
+.qaelem { position: absolute; top: 0; left: 0; right: 0; bottom: 0; }
diff --git a/web/reviewer.js b/web/reviewer.js
index 1f8962ac6..799ead72c 100644
--- a/web/reviewer.js
+++ b/web/reviewer.js
@@ -1,27 +1,77 @@
var ankiPlatform = "desktop";
var typeans;
-function _updateQA(q, answerMode, klass) {
- $("#qa").html(q);
+var currentAns = "_answer1";
+var nextAns = "_answer2";
+var fadeTime = 200;
+
+function _switchAnswerTarget() {
+ if (currentAns === "_answer1") {
+ currentAns = "_answer2";
+ nextAns = "_answer1";
+ } else {
+ currentAns = "_answer1";
+ nextAns = "_answer2";
+ }
+}
+
+function _makeVisible(jquery) {
+ return jquery.css("visibility", "visible").css("opacity", "1");
+}
+
+function _makeHidden(jquery) {
+ // must alter visibility as well so hidden elements are not clickable
+ return jquery.css("visibility", "hidden").css("opacity", "0");
+}
+
+function _showQuestion(q, a, bodyclass) {
+ document.body.className = bodyclass;
+
+ // update question text
+ _makeHidden($("#_question")).html(q);
+
+ // preload answer
+ _makeHidden($("#"+nextAns)).html(a);
+
+ // fade out previous answer
+ $("#"+currentAns).fadeTo(fadeTime, 0, function () {
+ // hide fully
+ _makeHidden($("#"+currentAns));
+ // and reveal question when processing is done
+ MathJax.Hub.Queue(function () {
+ $("#_question").css("visibility", "visible").fadeTo(fadeTime, 1);
+ });
+ });
+
+ // focus typing area if visible
typeans = document.getElementById("typeans");
if (typeans) {
typeans.focus();
}
- if (answerMode) {
- var e = $("#answer");
- if (e[0]) {
- e[0].scrollIntoView();
- }
- } else {
- window.scrollTo(0, 0);
- }
- if (klass) {
- document.body.className = klass;
- }
+
+ // return to top of window
+ window.scrollTo(0, 0);
+
// don't allow drags of images, which cause them to be deleted
$("img").attr("draggable", false);
+
+ // render mathjax
MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
}
+function _showAnswer(nextQuestion){
+ // hide question; show answer
+ _makeHidden($("#_question"));
+ _makeVisible($("#"+nextAns));
+
+ // scroll to answer?
+ var e = $("#answer");
+ if (e[0]) {
+ e[0].scrollIntoView();
+ }
+
+ _switchAnswerTarget();
+}
+
function _toggleStar(show) {
if (show) {
$(".marked").show();