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();