summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2018-06-16 14:40:57 +0900
committerNorbert Preining <norbert@preining.info>2018-06-16 14:40:57 +0900
commit5bf15133ae1a0745a8a5093950961c4e23dd8f5b (patch)
tree93f781068c7a66e17760e8ce4a3ad4a87b72f884
parent17a613f5d465d7e6560f3e4a76e1c7298889cbdb (diff)
add eq-save
-rw-r--r--texmf-dist/doc/latex/eq-save/README.md30
-rw-r--r--texmf-dist/doc/latex/eq-save/eqsave-man.pdfbin0 -> 249427 bytes
-rw-r--r--texmf-dist/doc/latex/eq-save/eqsave-man.tex351
-rw-r--r--texmf-dist/doc/latex/eq-save/examples/eqsave-name.tex134
-rw-r--r--texmf-dist/doc/latex/eq-save/examples/eqsave-noname.pdfbin0 -> 108324 bytes
-rw-r--r--texmf-dist/doc/latex/eq-save/examples/eqsave-noname.tex124
-rw-r--r--texmf-dist/source/latex/eq-save/eq-save.dtx646
-rw-r--r--texmf-dist/source/latex/eq-save/eq-save.ins60
-rw-r--r--texmf-dist/tex/latex/eq-save/eq-save.sty384
-rw-r--r--tlpkg/tlpsrc/eq-save.tlpsrc0
10 files changed, 1729 insertions, 0 deletions
diff --git a/texmf-dist/doc/latex/eq-save/README.md b/texmf-dist/doc/latex/eq-save/README.md
new file mode 100644
index 00000000..47c13ad8
--- /dev/null
+++ b/texmf-dist/doc/latex/eq-save/README.md
@@ -0,0 +1,30 @@
+The eq-save Package
+Author: D. P. Story
+Dated: 2018-04-07
+
+In the past, Adobe Reader did not save form data; consequently, work done by
+the student is lost when the AeB document is closed. In the more recent
+versions, beginning perhaps with version~11, AR can save form data. The
+eq-save package was written at a user's request to save all the quiz data so
+that the student does not lose his/her results after saving and closing the
+document.
+
+Use this package if you are writing tutorial or worksheets using the exerquiz
+package, the package enables the student to continue reading and work through
+the document over several sessions.
+
+Interactive document, such as those produced by AeB (including exerquiz)
+require Adobe Reader. Any such AeB document must be viewed in AR, outside a
+browser.
+
+What's New (2018-04-07) Bug fix, occassionally the data was not being
+recorded correctly.
+
+Package works for dvips/Distiller, pdflatex, lualatex, and xelatex.
+
+Enjoy!
+
+Now, I must get back to my retirement.
+
+dps
+dpstory at uakron dot edu
diff --git a/texmf-dist/doc/latex/eq-save/eqsave-man.pdf b/texmf-dist/doc/latex/eq-save/eqsave-man.pdf
new file mode 100644
index 00000000..f7467bc9
--- /dev/null
+++ b/texmf-dist/doc/latex/eq-save/eqsave-man.pdf
Binary files differ
diff --git a/texmf-dist/doc/latex/eq-save/eqsave-man.tex b/texmf-dist/doc/latex/eq-save/eqsave-man.tex
new file mode 100644
index 00000000..5efff180
--- /dev/null
+++ b/texmf-dist/doc/latex/eq-save/eqsave-man.tex
@@ -0,0 +1,351 @@
+\documentclass{article}
+\usepackage[fleqn]{amsmath}
+\usepackage[
+ web={centertitlepage,designv,forcolorpaper,tight*,latextoc,pro},
+ eforms,aebxmp
+]{aeb_pro}
+\usepackage{eq-save}
+\usepackage[ImplMulti]{dljslib}
+\usepackage{graphicx,array,fancyvrb}
+\usepackage{aeb_mlink}
+%\usepackage{myriadpro}
+%\usepackage{calibri}
+\usepackage[altbullet]{lucidbry}
+
+\def\hardspace{{\fontfamily{cmtt}\selectfont\symbol{32}}}
+
+\usepackage{acroman}
+\usepackage[active]{srcltx}
+
+\urlstyle{tt}
+
+\def\STRUT{\rule{0pt}{14pt}}
+\useBeginQuizButton[\CA{Begin}]
+\useEndQuizButton[\CA{End}]
+
+\makeatletter
+\newcount\hesheCnt \hesheCnt=-1
+\def\heshe{\@ifstar{\heshei}{\global\advance\hesheCnt1\relax\heshei}}
+\def\heshei{\ifodd\hesheCnt she\else he\fi}
+\def\HeShe{\@ifstar{\HeShei}{\global\advance\hesheCnt1\relax\HeShei}}
+\def\HeShei{\ifodd\hesheCnt She\else He\fi}
+\def\hisher{\@ifstar{\hisheri}{\global\advance\hesheCnt1\relax\hisheri}}
+\def\hisheri{\ifodd\hesheCnt her\else his\fi}
+\def\himher{\@ifstar{\himheri}{\global\advance\hesheCnt1\relax\himheri}}
+\def\himheri{\ifodd\hesheCnt her\else him\fi}
+\makeatother
+
+\DeclareDocInfo
+{
+ university={\AcroTeX.Net},
+ title={The \textsf{eq-save} Package},
+ author={D. P. Story},
+ email={dpstory@acrotex.net},
+ subject=Documentation for the eq-save package,
+ talksite={\url{www.acrotex.net}},
+ version={1.1, 2018/04/07},
+ Keywords={LaTeX, form field, hints, AcroTeX},
+ copyrightStatus=True,
+ copyrightNotice={Copyright (C) \the\year, D. P. Story},
+ copyrightInfoURL={http://www.acrotex.net}
+}
+
+\universityLayout{fontsize=Large}
+\titleLayout{fontsize=LARGE}
+\authorLayout{fontsize=Large}
+\tocLayout{fontsize=Large,color=aeb}
+\sectionLayout{indent=-62.5pt,fontsize=large,color=aeb}
+\subsectionLayout{indent=-31.25pt,color=aeb}
+\subsubsectionLayout{indent=0pt,color=aeb}
+\subsubDefaultDing{\texorpdfstring{$\bullet$}{\textrm\textbullet}}
+
+\chngDocObjectTo{\newDO}{doc}
+\begin{docassembly}
+var titleOfManual="The eq-save Package";
+var manualfilename="Manual_BG_Print_eq-save.pdf";
+var manualtemplate="Manual_BG_Brown.pdf"; // Blue, Green, Brown
+var _pathToBlank="C:/Users/Public/Documents/ManualBGs/"+manualtemplate;
+var doc;
+var buildIt=false;
+if ( buildIt ) {
+ console.println("Creating new " + manualfilename + " file.");
+ doc = \appopenDoc({cPath: _pathToBlank, bHidden: true});
+ var _path=this.path;
+ var pos=_path.lastIndexOf("/");
+ _path=_path.substring(0,pos)+"/"+manualfilename;
+ \docSaveAs\newDO ({ cPath: _path });
+ doc.closeDoc();
+ doc = \appopenDoc({cPath: manualfilename, oDoc:this, bHidden: true});
+ f=doc.getField("ManualTitle");
+ f.value=titleOfManual;
+ doc.flattenPages();
+ \docSaveAs\newDO({ cPath: manualfilename });
+ doc.closeDoc();
+} else {
+ console.println("Using the current "+manualfilename+" file.");
+}
+var _path=this.path;
+var pos=_path.lastIndexOf("/");
+_path=_path.substring(0,pos)+"/"+manualfilename;
+\addWatermarkFromFile({
+ bOnTop:false,
+ bOnPrint:false,
+ cDIPath:_path
+});
+\executeSave();
+\end{docassembly}
+
+
+\begin{document}
+
+\maketitle
+
+\selectColors{linkColor=black}
+\tableofcontents
+\selectColors{linkColor=webgreen}
+
+
+\section{Introduction}
+
+In this documentation, the one reading an \AEB\footnote{{\AcroTeX} eDucation
+Bundle} document is referred to as a student, as that is the intended target
+audience for education materials developed by the various packages of \AEB.
+
+The \pkg{exerquiz} package defines the \env{oQuestion}, \env{shortquiz}, and
+\env{quiz} environments that are used to pose interactive questions to
+students. The original concept of \pkg{exerquiz} was as an integral component
+in the development of education materials such as digital tutorials or
+worksheets. A student may work through such a document, learning concepts and
+answering questions to reinforce {\hisher} understanding.
+
+In the past, \app{Adobe Reader} (now \app{Adobe Acrobat Reader})---henceforth
+referred to as \app{AR}--- did not save form data; consequently, work done by
+the student is lost when the document is closed. In the more recent versions,
+beginning perhaps with version~11, \app{AR} can now save form data. The
+\pkg{eq-save} package was written at a user's request to save all the quiz
+data so that the student does not lose {\hisher} results after saving and
+closing the document.
+
+To be clear, when a {\PDF} (by \app{AR}) document is saved, the form data is
+also saved: the value of the field and properties of the field, such as
+border color, are saved. However, \pkg{exerquiz} keeps running tallies on the
+student's progress through the document, these are in the form of JavaScript
+variables, arrays and objects; the current values of these are \emph{not
+saved} with the document. Therefore, if the student saves the \PDF, it is
+necessary to save a minimal amount of information that can later be used to
+reconstruct the state of the document at the time student saved and closed the
+document. This `state data' is saved to a hidden text field. When the
+document is opened again, this hidden field is read, and the state of the
+document is minimally restored.
+
+\section{Requirements and options of the package}
+
+The \pkg{eq-save} package, being a support package, requires \pkg{exerquiz},
+dated 2017/07/30 or later. Use the package in the usual way,
+\begin{Verbatim}[xleftmargin=\amtIndent,commandchars=!()]
+\documentclass{article}
+\usepackage[!ameta(options)]{exerquiz}
+\usepackage[!ameta(options)]{eq-save}
+\end{Verbatim}
+There are only two options for \pkg{eq-save}, these are \opt{devmode} and
+\opt{!devmode}.\marginpar{\small\hfill\mbox{\parbox[t]{\marginparwidth}{\raggedleft
+\mbox{Options:\hspace{15pt}} \opt{devmode} \opt{!devmode}}}} As we shall see
+below, there is an optional `gatekeeper' command \cs{nameField}. The student
+is not allowed to peek at the document until a name is entered (preferably
+the student's own name) into the \cs{nameField}. When the \cs{nameField} and
+its companion \cs{BeginNoPeeking} are present it is rather inconvenient to
+develop the document, create and test quizzes because the author must first
+pass the `gatekeeper'. When the \opt{devmode} is in force, entering a name in
+\cs{nameField} is no longer required to view the rest of the document. The
+other option, \opt{!devmode} is the opposite of \opt{devmode}, that is, when
+\cs{nameField} and \cs{BeginNoPeeking} are present in the document, the
+student (or author) must enter a name into the name field before viewing the
+rest of the document. The \opt{!devmode} option is the default, passing no
+option is the same as passing \opt{!devmode}.
+
+\section{Basic commands}
+
+Actually, without any of the supporting commands, yet to be described, the
+document may be saved, closed, opened again. The responses to questions
+within the \env{oQuestion} and \env{shortquiz} environments are as when they
+were saved, the same is true for a full quiz of a \env{quiz} environment. So
+what is the need for this document? This package provides \emph{bookkeeping
+services}. Before continuing, let's illustrate by example. Answer one of the
+\env{shortquiz} questions and answer both questions from the \env{quiz}
+environment. Save the document, open and return to the page. When you return
+answer (correctly) the other question and/or change the answer for the other
+questions.\previewOff
+\begin{shortquiz*}[sQz1]
+Answer each of these to test your understanding.
+\begin{questions}
+ \item Select the two mathematicians recognized as the originators of Calculus.\marginpar{\small\raggedleft \emph{Hint:} N\&L}
+\begin{manswers}{5}
+ \bChoices
+ \Ans0 Banach\eAns
+ \Ans1 Newton\eAns
+ \Ans0 Hilbert\eAns
+ \Ans1 Liebniz\eAns
+ \eChoices
+\end{manswers}
+ \item $ 1 + 16 = \RespBoxMath[\rectW{.5in}]{17}{1}{.0001}{[0,1]}\olBdry\relax\CorrAnsButton{17}$
+ \item Which of the individuals below is the originator of \TeX?
+\begin{answers}{5}
+ \bChoices
+ \Ans0 Goossens\eAns
+ \Ans0 Rahtz\eAns
+ \Ans0 Mittelback\eAns
+ \Ans0 Lamport\eAns
+ \Ans1 Knuth\eAns
+ \eChoices
+\end{answers}
+\end{questions}
+\end{shortquiz*}
+\noindent
+Now complete this quiz consisting of the first two questions above, for simplicity.
+\begin{quiz*}{qz1}
+Respond to each without error. Passing is 100\%.
+\begin{questions}
+ \item Select the two mathematicians recognized as the originators of Calculus.
+\begin{manswers}{5}
+ \bChoices
+ \Ans0 Banach\eAns
+ \Ans1 Newton\eAns
+ \Ans0 Hilbert\eAns
+ \Ans1 Liebniz\eAns
+ \eChoices
+\end{manswers}
+ \item $ 1 + 16 = \RespBoxMath[\rectW{.5in}]{17}{1}{.0001}{[0,1]}$
+\end{questions}
+\end{quiz*}\cgBdry[.5em]\ScoreField\currQuiz\CorrButton\currQuiz\hfill Answers: \AnswerField[\rectW{1in}]\currQuiz\vcgBdry[6pt]
+\hfill\ding{172}\enspace\sooField{1in}{11bp}\cgBdry\clearAllField{}{11bp}\vcgBdry[12pt]
+The field labeled with `\ding{172}' is one of the new fields, as is the one
+to its right. As you work through the above questions, the field keeps track
+of your success rate in all quizzes (from the \env{oQuestion},
+\env{shortquiz}, and \env{quiz} environments). When you save, close, and open
+again, the tally continues where it left off. Ideal for working through a
+long document. The field `\textsf{Clear All}' clears all quiz results as well as
+the field labeled `\ding{172}', then all is forgotten.
+
+Before continuing on to the discussion of the various commands of this
+package, several observations are appropriate.
+\begin{itemize}
+ \item As soon as you respond to an \emph{immediate-feedback question} (a question
+ from either the \env{oQuestion} or \env{shortquiz} environment), the
+ total number of questions of this type is known, its 4 for this set of
+ questions. In the \textcolor{red}{Quiz}, problem~1 is a multiple
+ selection (MS) question with two correct answers; problem~2 has one correct
+ answer; problem~3 is multiple choice (MC), only one correct question.
+ There is a total of 4 ($\text{two}+\text{one}+\text{one}=4$).
+ \item As you answer more immediate-feedback questions, or change your
+ answers from a correct ones to an incorrect ones, the tally changes
+ appropriately, but always says `out of 4' (in this set of quizzes).
+ \item The quiz (as constructed from the \env{quiz} environment) has only
+ two questions, but the tally box does not know this until
+ `\textsf{Begin}' and `\textsf{End}' are pressed. A quiz consists of
+ \emph{delayed-feedback} questions.
+
+ \item Results (for the quiz) are not known until the `\textsf{End}' button
+ is pressed, then the tally field `\ding{172}' is updated. You'll note
+ that the multiple selection (MS) question only contributes one (1) to
+ the `out of' number, that's because MS is scored differently than it is
+ for immediate-feedback.
+
+\end{itemize}
+
+\subsection{Bookkeeping commands}\previewOff
+
+The `bookkeeping' commands are create text field to hold ongoing tally data.
+\bVerb\takeMeasure{\string\sooField[\ameta{opts}]\darg{\ameta{width}}\darg{\ameta{height}}}%
+\setlength\aebscratch{\bxSize}%
+\def\1{\makebox[0pt][l]{\hspace{\aebscratch}\enspace\makebox[0pt][l]{\hspace{.5in}\enspace\normalfont(score field)}\sField[\textSize{7}]{.5in}{9bp}}}%
+\def\2{\makebox[0pt][l]{\hspace{\aebscratch}\enspace\makebox[0pt][l]{\hspace{.5in}\enspace\normalfont(`out of' field)}\ooField[\textSize{7}]{.5in}{9bp}}}%
+\def\3{\makebox[0pt][l]{\hspace{\aebscratch}\enspace\makebox[0pt][l]{\hspace{.5in}\enspace\normalfont(combined score field)}\sooField[\textSize{7}]{.5in}{9bp}}}%
+\begin{dCmd}[commandchars=!()]{\bxSize}
+!1\sField[!ameta(opts)]{!ameta(width)}{!ameta(height)}
+!2\ooField[!ameta(opts)]{!ameta(width)}{!ameta(height)}
+!3\sooField[!ameta(opts)]{!ameta(width)}{!ameta(height)}
+\end{dCmd}
+\eVerb All three field generate a text field with dimensions \ameta{width}
+and \ameta{height}, the \meta{opt} allows you to pass \pkg{eforms} field
+options to change the appearance of the field. \cs{sField} holds only the number of question answered correctly;
+\cs{ooField} holds the `out of' value, the number of questions detected; \cs{sooField} is a combination of
+the first two values, typically is displays `3 out of 6'. The `out of' phrase is the expansion of \cs{eqOutOf}, a command
+defined and documented in \pkg{exerquiz}. A convenience way of redefining the `out of' phrase is through \cs{declareScorePhrase}:
+\bVerb\takeMeasure{\string\declareScorePhrase\darg{\#1+"\string\space\string\eqOutOf\string\space"+\#2}}%
+\setlength\aebscratch{\bxSize}%
+\def\1{\makebox[0pt][l]{\hspace{\aebscratch}\enspace\normalfont(default definition)}}%
+\begin{dCmd}[commandchars=!()]{\bxSize}
+\declareScorePhrase{!ameta(JS-str)}
+!1\declareScorePhrase{#1+"\space\eqOutOf\space"+#2}
+\end{dCmd}
+\eVerb The argument \ameta{JS-str} is a JavaScript string. It is phrased using \texttt{\#1} and \texttt{\#2}, which at
+compile time, are replaced with JavaScript variables that will hold the score value and the `out of' value.
+
+\newtopic With \pkg{exequiz} you can also assign points for questions in \env{quiz} environments; as a consequence, there is
+a similar set of commands to those above.
+\bVerb\takeMeasure{\string\psooField[\ameta{opts}]\darg{\ameta{width}}\darg{\ameta{height}}}%
+\begin{dCmd}[commandchars=!()]{\bxSize}
+\psField[!ameta(opts)]{!ameta(width)}{!ameta(height)}
+\pooField[!ameta(opts)]{!ameta(width)}{!ameta(height)}
+\psooField[!ameta(opts)]{!ameta(width)}{!ameta(height)}
+\end{dCmd}
+\eVerb These fields report the point totals. For \env{oQuestion} and \env{shortquiz} environments, each question is only 1 point, but
+for \env{quiz} environment you can assign points using the \cs{PTs} command, as illustrated the documentation of \AEB. We do not illustrate
+this set of commands in the documentation.
+
+To clear all the fields just described, as well as all fields in the \env{oQuestion}, \env{shortquiz} and
+\env{quiz} environment, insert the \cs{clearAllField} into your document.
+\bVerb\takeMeasure{\string\clearAllField[\ameta{opts}]\darg{\ameta{width}}\darg{\ameta{height}}}%
+\begin{dCmd}[commandchars=!()]{\bxSize}
+\clearAllField[!ameta(opts)]{!ameta(width)}{!ameta(height)}
+\end{dCmd}
+\eVerb The interpretation of the parameters are as above.
+
+
+\subsection{Gatekeeper commands}
+
+The application that inspired this package was the Professor of the course did not want the student to look at the quizzes
+until {\heshe} entered {\hisher*} name. As a result, should you want this sort of `security', include the \cs{nameField}
+and \cs{BeginNoPeeking} commands. The latter should begin on the first page you don't want your students to look upon until
+they enter their names.
+\bVerb\takeMeasure{\string\flJSStr[noquotes,noparens]\darg{\string\EnterNameFirstMsg}\darg{\ameta{msg}}}%
+\begin{dCmd}[commandchars=!()]{\bxSize}
+\nameField[!ameta(opts)]{!ameta(name)}{!ameta(width)}{!ameta(height)}
+\BeginNoPeeking
+!STRUT\flJSStr[noquotes,noparens]{\EnterNameFirstMsg}{!ameta(msg)}
+\end{dCmd}
+\eVerb The \meta{name} field allows you to enter a personalized field name,
+such as `\texttt{IhrName}', or something. The other parameters are the same
+as above and are described briefly in the description of \cs{sField}.
+
+When the student enters {\hisher} name, the document is cleared: all fields
+that support questions from the \env{oQuestion}, \env{shortquiz}, and
+\env{quiz} environments; all fields whose commands begin with `s', `oo',
+`soo', `ps', `poo', and `psoo' fields, as described above. This is a weak
+security measure to make it more difficult for a student to just take the
+worksheet of an `A' student and simply remove the name and enter {\hisher}
+own name. Of course, unless students supervised in a lab, these measures are
+only inconveniences.
+
+There are two JavaScript strings that can be rephrased or localized. The default
+declarations are,
+\begin{Verbatim}[xleftmargin=\amtIndent,commandchars=!()]
+\flJSStr[noquotes,noparens]{\EnterNameFirstMsg}
+!qquad{You must enter your name first!}
+!STRUT\dlJSStr{\eqerrUnfinishQuizAtSave}{One of your quizzes
+!qquad(is not finished, you will lose those responses.)}
+
+\end{Verbatim}
+
+\section{Demonstration files}
+
+There are two sample files, \texttt{eqsave-name.tex} and
+\texttt{eqsave-noname.tex}, found in the \texttt{examples} folder. The first
+has uses the gatekeeper commands (these are \cs{sField} and \cs{BeginNoPeeking}), while the
+second one does not; otherwise, the files are the same.
+
+\section{My retirement}
+
+Now, I simply must get back to it. \dps
+
+\end{document}
diff --git a/texmf-dist/doc/latex/eq-save/examples/eqsave-name.tex b/texmf-dist/doc/latex/eq-save/examples/eqsave-name.tex
new file mode 100644
index 00000000..743b464c
--- /dev/null
+++ b/texmf-dist/doc/latex/eq-save/examples/eqsave-name.tex
@@ -0,0 +1,134 @@
+\documentclass{article}
+\usepackage[fleqn]{amsmath}
+\usepackage{web}
+\usepackage{exerquiz}
+\usepackage[!devmode]{eq-save}
+\usepackage[ImplMulti]{dljslib}
+
+\def\lfootScore{\sField{.25in}{11bp}}
+\def\lfootOutOf{\ooField{.25in}{11bp}}
+\def\rfootPtsScore{\psField{.25in}{11bp}}
+\def\rfootPtsOutOf{\pooField{.25in}{11bp}}
+
+\lfooter{Score {\lfootScore} out of {\lfootOutOf}}
+\rfooter{Points {\rfootPtsScore} out of {\rfootPtsOutOf}}
+
+
+\previewOff
+\sqTurnOffAlerts
+\PTsHook{($\eqPTs^{\text{pts}}$)}
+
+\parindent0pt
+
+\begin{document}
+
+\begin{center}\bfseries\large
+ Demonstrating the \texttt{eq-save} package\\
+ Gatekeeper commands present\\[3pt]
+ \normalfont\normalsize Herr Dr Prof Story
+\end{center}
+
+Answer some of the questions, save the document, then reopen it and continue
+the `worksheet'. The tallies should continue from the values current at the
+time the document was saved.\medskip
+
+Begin by entering your name in the input box below.\medskip
+
+\textbf{Warning:} Clearing or changing the name field clears all quizzes. After you begin, do not change
+your name field or all entries will be lost.\bigskip
+
+Ihr Name: \nameField{IhrName}{2in}{11bp}
+
+\newpage
+% separate the name field from the rest of the content, insert \BeginNoPeeking
+\BeginNoPeeking
+
+\begin{oQuestion}{oQ1}
+It is well known that $ 1 + 16 = \RespBoxMath{17}{1}{.0001}{[0,1]}$
+\end{oQuestion}
+
+\begin{shortquiz*}[sQ1]
+Solve each of the following without error.
+\begin{questions}
+
+\item Calculate: $ 8 \cdot 11 = \RespBoxMath{88}{1}{.0001}{[0,1]}$
+\item Enter the \emph{last name} of the Herr Dr Prof of this course.
+\[
+ \text{The Herr Dr Prof is }\RespBoxTxt{1}{0}{1}{Story}
+\]
+ \item Which of the following is true
+\begin{answers}{4}
+\bChoices
+ \Ans1 true\eAns
+ \Ans0 false\eAns
+\eChoices
+\end{answers}
+\item From the list below, select the mathematicians recognized as the originators of Calculus.
+\begin{manswers}{4}
+\bChoices
+ \Ans1 Newton\eAns
+ \Ans0 Gauss\eAns
+ \Ans1 Leibniz\eAns
+ \Ans0 Banach\eAns
+\eChoices
+\end{manswers}
+\end{questions}
+\end{shortquiz*}
+
+
+\useBeginQuizButton
+\useEndQuizButton
+
+\begin{quiz*}{qz1}
+Solve each without error.
+\begin{questions}
+ \item Which of the following is true
+\begin{answers}{2}
+ \Ans1 true & \Ans0 false
+\end{answers}
+\item Calculate: $ 8 \cdot 11 = \RespBoxMath{88}{1}{.0001}{[0,1]}$
+\item From the list below, select the mathematicians recognized as the originators of Calculus.
+\begin{manswers}{4}
+\bChoices
+ \Ans1 Newton\eAns
+ \Ans0 Gauss\eAns
+ \Ans1 Leibniz\eAns
+ \Ans0 Banach\eAns
+\eChoices
+\end{manswers}
+\end{questions}
+\end{quiz*}\quad\ScoreField\currQuiz\olBdry\CorrButton\currQuiz
+
+
+
+\newpage
+
+The quiz on this page has points associated with each question, the points are tabulated separately,
+and entered into the fields in the right footer. The questions above are figured in as 1 point each.
+
+\begin{quiz*}{qz2}
+Solve each without error.
+\begin{questions}
+ \item\PTs{2} Which of the following is true
+\begin{answers}{2}
+\bChoices
+ \Ans1 true\eAns
+ \Ans0 false\eAns
+\eChoices
+\end{answers}
+\item\PTs{3} Calculate: $ 8 \cdot 11 = \RespBoxMath{88}{1}{.0001}{[0,1]}$
+\item\PTs{4} From the list below, select the mathematicians recognized as the originators of Calculus.
+\begin{manswers}{4}
+\bChoices
+ \Ans1 Newton\eAns
+ \Ans0 Gauss\eAns
+ \Ans1 Leibniz\eAns
+ \Ans0 Banach\eAns
+\eChoices
+\end{manswers}
+\end{questions}
+\end{quiz*}\quad\PointsField\currQuiz\olBdry\CorrButton\currQuiz
+
+
+\medskip\noindent\sooField{1in}{11bp}\olBdry\clearAllField{}{11bp}
+\end{document}
diff --git a/texmf-dist/doc/latex/eq-save/examples/eqsave-noname.pdf b/texmf-dist/doc/latex/eq-save/examples/eqsave-noname.pdf
new file mode 100644
index 00000000..5ec4b41a
--- /dev/null
+++ b/texmf-dist/doc/latex/eq-save/examples/eqsave-noname.pdf
Binary files differ
diff --git a/texmf-dist/doc/latex/eq-save/examples/eqsave-noname.tex b/texmf-dist/doc/latex/eq-save/examples/eqsave-noname.tex
new file mode 100644
index 00000000..4ec47d6c
--- /dev/null
+++ b/texmf-dist/doc/latex/eq-save/examples/eqsave-noname.tex
@@ -0,0 +1,124 @@
+\documentclass{article}
+\usepackage[fleqn]{amsmath}
+\usepackage{web}
+\usepackage{exerquiz}
+\usepackage[!devmode]{eq-save}
+\usepackage[ImplMulti]{dljslib}
+
+\def\lfootScore{\sField{.25in}{11bp}}
+\def\lfootOutOf{\ooField{.25in}{11bp}}
+\def\rfootPtsScore{\psField{.25in}{11bp}}
+\def\rfootPtsOutOf{\pooField{.25in}{11bp}}
+
+\lfooter{Score {\lfootScore} out of {\lfootOutOf}}
+\rfooter{Points {\rfootPtsScore} out of {\rfootPtsOutOf}}
+
+
+\previewOff
+\sqTurnOffAlerts
+\PTsHook{($\eqPTs^{\text{pts}}$)}
+
+\parindent0pt
+
+\begin{document}
+
+
+\begin{center}\bfseries\large
+ Demonstrating the \texttt{eq-save} package\\
+ No Gatekeeper commands present\\[3pt]
+ \normalfont\normalsize Herr Dr Prof Story
+\end{center}
+
+Answer some of the questions, save the document, then reopen it and continue
+the `worksheet'. The tallies should continue from the values current at the
+time the document was saved.\medskip
+
+\begin{oQuestion}{oQ1}
+It is well known that $ 1 + 16 = \RespBoxMath{17}{1}{.0001}{[0,1]}$
+\end{oQuestion}
+
+\begin{shortquiz*}[sQ1]
+Solve each of the following without error.
+\begin{questions}
+
+\item Calculate: $ 8 \cdot 11 = \RespBoxMath{88}{1}{.0001}{[0,1]}$
+\item Enter the \emph{last name} of the Herr Dr Prof of this course.
+\[
+ \text{The Herr Dr Prof is }\RespBoxTxt{1}{0}{1}{Story}
+\]
+ \item Which of the following is true
+\begin{answers}{4}
+\bChoices
+ \Ans1 true\eAns
+ \Ans0 false\eAns
+\eChoices
+\end{answers}
+\item From the list below, select the mathematicians recognized as the originators of Calculus.
+\begin{manswers}{4}
+\bChoices
+ \Ans1 Newton\eAns
+ \Ans0 Gauss\eAns
+ \Ans1 Leibniz\eAns
+ \Ans0 Banach\eAns
+\eChoices
+\end{manswers}
+\end{questions}
+\end{shortquiz*}
+
+
+\useBeginQuizButton
+\useEndQuizButton
+
+\begin{quiz*}{qz1}
+Solve each without error.
+\begin{questions}
+ \item Which of the following is true
+\begin{answers}{2}
+ \Ans1 true & \Ans0 false
+\end{answers}
+\item Calculate: $ 8 \cdot 11 = \RespBoxMath{88}{1}{.0001}{[0,1]}$
+\item From the list below, select the mathematicians recognized as the originators of Calculus.
+\begin{manswers}{4}
+\bChoices
+ \Ans1 Newton\eAns
+ \Ans0 Gauss\eAns
+ \Ans1 Leibniz\eAns
+ \Ans0 Banach\eAns
+\eChoices
+\end{manswers}
+\end{questions}
+\end{quiz*}\quad\ScoreField\currQuiz\olBdry\CorrButton\currQuiz
+
+
+
+\newpage
+
+The quiz on this page has points associated with each question, the points are tabulated separately,
+and entered into the fields in the right footer. The questions above are figured in as 1 point each.
+
+\begin{quiz*}{qz2}
+Solve each without error.
+\begin{questions}
+ \item\PTs{2} Which of the following is true
+\begin{answers}{2}
+\bChoices
+ \Ans1 true\eAns
+ \Ans0 false\eAns
+\eChoices
+\end{answers}
+\item\PTs{3} Calculate: $ 8 \cdot 11 = \RespBoxMath{88}{1}{.0001}{[0,1]}$
+\item\PTs{4} From the list below, select the mathematicians recognized as the originators of Calculus.
+\begin{manswers}{4}
+\bChoices
+ \Ans1 Newton\eAns
+ \Ans0 Gauss\eAns
+ \Ans1 Leibniz\eAns
+ \Ans0 Banach\eAns
+\eChoices
+\end{manswers}
+\end{questions}
+\end{quiz*}\quad\PointsField\currQuiz\olBdry\CorrButton\currQuiz
+
+
+\medskip\noindent\sooField{1in}{11bp}\olBdry\clearAllField{}{11bp}
+\end{document}
diff --git a/texmf-dist/source/latex/eq-save/eq-save.dtx b/texmf-dist/source/latex/eq-save/eq-save.dtx
new file mode 100644
index 00000000..180d42fe
--- /dev/null
+++ b/texmf-dist/source/latex/eq-save/eq-save.dtx
@@ -0,0 +1,646 @@
+% \iffalse
+%<*copyright>
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% eq-save package, %%
+%% Copyright (C) 2017-2018 %%
+%% dpstory@uakron.edu %%
+%% %%
+%% This program can redistributed and/or modified under %%
+%% the terms of the LaTeX Project Public License %%
+%% Distributed from CTAN archives in directory %%
+%% macros/latex/base/lppl.txt; either version 1.2 of %%
+%% the License, or (at your option) any later version. %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%</copyright>
+%<package>\NeedsTeXFormat{LaTeX2e}[1997/12/01]
+%<package>\ProvidesPackage{eq-save}
+%<package> [2018/04/07 v1.1 eq-save: save exerquiz quizzes and resume (dps)]
+%<*driver>
+\documentclass{ltxdoc}
+\usepackage[colorlinks,hyperindex=false]{hyperref}
+\usepackage{calc}
+\let\uif\textsf\let\app\textsf
+\let\pkg\textsf\let\env\texttt
+\let\opt\texttt
+\def\ameta#1{$\langle\textit{\texttt{#1}}\rangle$}
+\def\psf#1{\textsf{\textbf{#1}}}
+%\pdfstringdefDisableCommands{\let\\\textbackslash}
+\OnlyDescription % comment out for implementation details
+\EnableCrossrefs
+\CodelineIndex
+\RecordChanges
+\InputIfFileExists{aebdocfmt.def}{\PackageInfo{eq-save}{Inputting aebdocfmt.def}}
+ {\def\IndexOpt{\DescribeMacro}\def\IndexKey{\DescribeMacro}\let\setupFullwidth\relax
+ \PackageInfo{eq-save}{aebdocfmt.def cannot be found}}
+\begin{document}
+\def\CMD#1{\textbackslash#1}
+ \GetFileInfo{eq-save.sty}
+ \title{\textsf{eq-save}: Saving \pkg{exerquiz} quizzes and resuming}
+ \author{D. P. Story\\
+ Email: \texttt{dpstory@acrotex.net}}
+ \date{processed \today}
+ \maketitle
+ \tableofcontents
+ \let\Email\texttt
+ \renewenvironment{theglossary}{%
+ \let\efill\relax
+ \begin{itemize}}{\end{itemize}}
+ \value{GlossaryColumns}=1
+ \DocInput{eq-save.dtx}
+\IfFileExists{\jobname.ind}{\newpage\setupFullwidth\par\PrintIndex}{\paragraph*{Index} The index goes here.\\Execute
+ \texttt{makeindex -s gind.ist -o eq-save.ind eq-save.idx} on the command line and recompile
+ \texttt{eq-save.dtx}.}
+\IfFileExists{\jobname.gls}{\PrintChanges}{\paragraph*{Change History} The list of changes goes here.\\Execute
+ \texttt{makeindex -s gglo.ist -o eq-save.gls eq-save.glo} on the command line and recompile
+ \texttt{eq-save.dtx}.}
+\end{document}
+%</driver>
+% \fi
+% \MakeShortVerb{|}
+% \InputIfFileExists{aebdonotindex.def}{\PackageInfo{web}{Inputting aebdonotindex.def}}
+% {\PackageInfo{web}{cannot find aebdonotindex.def}}
+% \begin{macrocode}
+% Begin Package
+%<*package>
+% \end{macrocode}
+% The option \IndexOpt{devmode}\opt{devmode} does not require the user to enter his or her name
+% in the name field, if the \cs{nameField} and \cs{BeginNoPeeking} commands are present; otherwise it has no effect.
+% The \IndexOpt{!devmode}\opt{!devmode} is the logical negation of \opt{devmode}, its the same as no option
+% passed.
+% \begin{macrocode}
+\DeclareOption{devmode}{\def\devMode{true}}
+\DeclareOption{!devmode}{\def\devMode{false}}
+\def\devMode{false}
+\ProcessOptions
+\RequirePackage{exerquiz}[2017/07/30]
+\RequirePackage{atbegshi}
+\edef\ap@restoreCats{%
+ \catcode`\noexpand\"=\the\catcode`\"\relax
+ \catcode`\noexpand\,=\the\catcode`\,\relax
+ \catcode`\noexpand\(=\the\catcode`\(\relax
+ \catcode`\noexpand\!=\the\catcode`\!\relax
+}
+\@makeother\"\@makeother\,\@makeother\(\@makeother\!
+% \end{macrocode}
+% \changes{v1.0}{2017/08/12}{Wrote initial documentation, set version as v1.0}
+% \section{Introduction}
+% Work, on what ultimately became this package, was initiated by a user Manfred~S. He and his team were writing
+% practice documents for their students that included \env{oQuestion}, \env{shortquiz}, and \env{quiz} environments from the
+% \pkg{exerquiz} package. It was desired for the student to enter his/her name first, then begin the practice document.
+% After a while, the student may become tired or disinterested, so he/she save the document.
+% He wanted to take advantage of the ability of Adobe Acrobat Reader 11 or greater (DC and beyond) to save the form data,
+% something it couldn't do prior. Later the student becomes motivated and returns to the document to continue working through
+% the questions.
+%
+% Sounds good, but wait! \env{oQuestion}, \env{shortquiz}, and \env{quiz} environments were not designed
+% for this. There are a lot of JavaScript variables, arrays, objects containing information about the quizzes as they are
+% attempted. This data is normally disposed of when the reader takes another quiz. Certainly, as the user saves and closes
+% the document all variables, arrays, objects are lost. This package attempts to save all essential information when
+% the user saves the document, the information is saved in a hidden text field. Upon opening the document again,
+% the essential data is restored.
+%
+% A professor might want this feature for a tutorial. The tutorial (rather long) can have questions from
+% \env{oQuestion}, \env{shortquiz}, and \env{quiz} environments. The student can save, and return to the
+% reading of the tutorial and the answering of the questions. A self-paced tutorial does not need a name field
+% to act as a `gatekeeper' to the document, as is the need of Manfred~S.
+%
+%
+% \section{Commands of this package}
+% The \DescribeMacro{\nameField}\cs{nameField} command insert a text field into which the student enters
+% his name; otherwise, he cannot continue to the next page. Changing your name after you've begun to work
+% on the questions clears the answer to all quizzes; this is an annoyance factor, a feeble attempt to reduce
+% cheating. When \cs{nameField} is used, the top of the next page should be \cs{BeginNoPeeking}.
+% \begin{macrocode}
+\newcommand\nameField[4][]{\textField[#1
+ \AAkeystroke{chk4PassToQuestions(event);}
+ \AAformat{if(typeof oRecordOfQuizData=="undefined") \r\t
+ var oRecordOfQuizData=new Object();\r
+ try{IhrNameFormat(event);}catch(e){}
+ }]{#2}{#3}{#4}}
+% \end{macrocode}
+% \DescribeMacro{\hiddenScoreData}\cs{hiddenScoreData} text field.
+% It has zero dimensions, takes up no (horizontal) {\TeX} space, and is hidden. It is placed under the name field.
+% This field, when the document is saved, receive all essential quiz data. It is read again when the document
+% is opened to restore the quiz data. We give this field an initial value, for otherwise, the PDF viewer will
+% not scan this field on opening.
+% \begin{macrocode}
+\newcommand{\hiddenScoreData}{\makebox[0pt][l]{%
+\textField[\F\FHidden\V{({})}\DV{({})}\AAformat{%
+ if(typeof oRecordOfQuizData=="undefined")\r\t
+ oRecordOfQuizData={};}\BG{}\BC{}]{holdScoreData}{0bp}{0bp}}}
+\AtBeginShipoutFirst{\hiddenScoreData}
+% \end{macrocode}
+% We place this field on the first page, upper left corner. It will be scanned by the PDF viewer (Reader)
+% and it will define the object \texttt{oRecordOfQuizData} that will hold essential quiz data.
+%
+% \paragraph*{Displaying and clearing results} As the user/student progresses through the documents, he
+% can see his success rate by viewing the text fields below.
+%
+% The \DescribeMacro{\sooField}\cs{sooField} (soo=score out of) displays the combined score: `12 out of 16', for example.
+% The phase may be redefined for language purposes by redeclaring the command \cs{declareScorePhrase}, the English
+% declaration is \verb~\declareScorePhrase{#1+"\space\eqOutOf\space"+#2}~, see the documentation above for this command.
+%
+% The \DescribeMacro{\sField}\cs{sField} is one that holds only the score, while
+% \DescribeMacro{\ooField}\cs{ooField} holds the `out of' value.
+% \begin{macrocode}
+\newcommand{\sField}[3][]{\textField[\Ff{\FfReadOnly}#1]%
+ {\eqsroot.Score}{#2}{#3}}
+\newcommand{\ooField}[3][]{\textField[\Ff{\FfReadOnly}#1]%
+ {\eqsroot.OutOf}{#2}{#3}}
+\newcommand{\sooField}[3][]{\textField[\Ff{\FfReadOnly}#1]%
+ {\eqsroot.ScoreComb}{#2}{#3}}
+% \end{macrocode}
+% Now we do the same thing for the points score. \DescribeMacro{\psField}\cs{psField} holds the total
+% number of points awarded; \DescribeMacro{\pooField}\cs{pooField} is the total number of points;
+% \DescribeMacro{\psooField}\cs{psooField}
+% \begin{macrocode}
+\newcommand{\psField}[3][]{\textField[\Ff{\FfReadOnly}#1]%
+ {\eqsroot.ptScore}{#2}{#3}}
+\newcommand{\pooField}[3][]{\textField[\Ff{\FfReadOnly}#1]%
+ {\eqsroot.ptOutOf}{#2}{#3}}
+\newcommand{\psooField}[3][]{\textField[\Ff{\FfReadOnly}#1]%
+ {\eqsroot.ptScoreComb}{#2}{#3}}
+% \end{macrocode}
+% We supply a global clearing button. This button clear all results in the document, questions posed
+% by \env{oQuestions}, \env{shortquiz}, and \env{quiz} environments.
+% \begin{macrocode}
+\newcommand{\clearAllField}[3][]{\pushButton[\CA{Clear All}#1
+ \AAmouseup{clearAllSQElements();}]{globalClearAll}{#2}{#3}}
+% \end{macrocode}
+%
+% \paragraph*{Set action keys} We modify certain action keys to save the information we'll need later when the document is saved.
+% The \cs{setActionKeys} is a new feature of \pkg{exerquiz} (2017/07/29) and is used to add JavaScript
+% actions to certain key elements of the quiz environments. This is how we are able to preserve and later
+% restore the quiz data. The command \DescribeMacro{\eqsSetActionKeys}\cs{eqsSetActionKeys} is expanded
+% when \cs{DeclareReportRootName} is expanded. If the author declares a new root, the \cs{setActionKeys},
+% which depend on \cs{eqsroot}, must be re-emitted.
+% \begin{macrocode}
+\newcommand{\eqsSetActionKeys}{%
+ \setActionKeys{%
+% \end{macrocode}
+% (2018/04/07) Removing \cs{AddAAFormat}, there is no test for null later in the code.
+% \changes{v1.1}{2018/04/07}{No need for the change to \string\cs{AddAAFormat}}
+% \begin{macrocode}
+% \AddAAFormat{\if\eqQuizType\isSQZ
+% if (typeof event.target.isCorrect=="undefined")\r\t
+% event.target.isCorrect=null;\fi}
+ \AddAAKeystroke{\if\eqQuizType\isSQZ
+ event.target.isCorrect=(retn)?1:0;\r\t
+ oRecordOfQuizData[event.target.name]=event.target.isCorrect;\r\t
+ cntCorrectResponses();\fi}
+ \AddAAMouseUpMC{\if\eqQuizType\isSQZ
+ event.target.isCorrect=\Ans@choice;\r
+ oRecordOfQuizData[event.target.name]=event.target.isCorrect;\r
+ cntCorrectResponses();\fi}
+ \AddAAMouseUpMS{\if\eqQuizType\isSQZ
+ event.target.isCorrect=\Ans@choice;\r
+ oRecordOfQuizData[event.target.name]=event.target.isCorrect;\r
+ cntCorrectResponses();\fi}
+ }%
+}
+% \end{macrocode}
+% \paragraph*{Modify actions of Begin Quiz and End Quiz} These actions may be modified using the
+% two commands \cs{postInitQuiz} and \cs{postSubmitQuiz}. They are used to insert the \texttt{cntCorrectResponses()} call
+% into the action performed by the `Begin Quiz' and `End Quiz' buttons. \emph{It is assumed the document
+% author is not otherwise using these two commands.}
+% \begin{macrocode}
+\def\postInitQuiz{%
+ var f=this.getField("ScoreData.\oField");\r
+ f.value="0;0;0;0";\r
+ cntCorrectResponses();}
+\def\postSubmitQuiz{%
+ oRecordOfQuizData["ScoreData.\oField"]=%
+ [1*Score,1*NQuestions,1*ptScore,1*NPointTotal];\r\t\t
+ cntCorrectResponses();\r
+}
+% \end{macrocode}
+% \paragraph*{Open Page Action} We add a page open event to restore the data as needed. We only do this once
+% per document session.
+% \begin{macrocode}
+\thisPageAction{\JS{if(!restoreQuizData.hasRestoredData)\r\t
+ var rqdTO=(app.setTimeOut("restoreQuizData();app.clearTimeOut(rqdTO);%
+ restoreQuizData.hasRestoredData=true",1000));}}{}
+% \end{macrocode}
+% \paragraph*{Action prior to saving} It is important to save the quiz data, we can only do that if we save
+% it to a field, the value of the field will be saved. We save the data to a hidden text field
+% \texttt{"holdScoreData"}, this field is required.
+% \begin{macrocode}
+\begin{willSave}
+isAQuizUnfinishedAtSave();
+if (typeof oRecordOfQuizData !="undefined") collectQuizData();
+\end{willSave}
+% \end{macrocode}
+% \paragraph*{No peeking} If the \cs{nameField} command is used,
+% use \DescribeMacro{\BeginNoPeeking}\cs{BeginNoPeeking} command can optionally appear on the
+% first page that contain content the author does not want the user to peek at. The
+% JavaScript string \DescribeMacro{\EnterNameFirstMsg}\cs{EnterNameFirstMsg} appears in the alert
+% box if the user goes to a forbidden page without first enther his name into the \cs{nameField}.
+% May be redefined for local languages.
+% \begin{macrocode}
+\flJSStr[noquotes,noparens]{\EnterNameFirstMsg}{You must enter
+ your name first!}
+\def\declareScorePhrase#1{\def\dclScorePhse(##1)(##2){#1}}
+\declareScorePhrase{#1+"\space\eqOutOf\space"+#2}
+\def\BeginNoPeeking{\def\IhrNamePO{\thisPageAction{%
+ \JS{if(!_docDevMode&&!_passToQuestions){\r\t
+ this.pageNum=0;\r\t
+ NoNameMsg=app.setTimeOut("app.alert('\EnterNameFirstMsg');%
+ app.clearTimeOut(NoNameMsg);",25);}}}{}}%
+% Page option for this page
+ \IhrNamePO
+% page open for all other pages
+ \AtBeginShipout{\IhrNamePO}%
+}
+% \end{macrocode}
+% The command \DescribeMacro{\DeclareReportRootName}\cs{DeclareReportRootName} may never need to be used, but just
+% in case, it can only be used once in the preamble. It names the parent (or root) name of the text fields that
+% will contain the running summary of the user's efforts in the document. The default root name is \texttt{SUMRY}.
+% \begin{macrocode}
+\newcommand{\DeclareReportRootName}[1]{\def\eqsroot{#1}%
+ \eqsSetActionKeys}
+\DeclareReportRootName{SUMRY}
+\@onlypreamble{\DeclareReportRootName}
+% \end{macrocode}
+% One of the problems is the quizzes and shortquizzes are not known when the document is first
+% opened. Normally this is not a problem, but in this application we need to know them. This problem
+% is solved by two events: at the end of the document the list of quizzes is known, it is save to
+% the auxiliary file \texttt{qzlist-\string\jobname.cut}, then this file is input back into the preamble, parsed,
+% and entered into the document level JavaScript through the command \cs{jsCodeForQzs}. The contents
+% of the aux file may look like: \texttt{\string\jsForQzs\space qz1;qz2;oQ1;sQ1;\string\@nil}. The internal command
+% \DescribeMacro{\jsCodeForQzs}\cs{jsCodeForQzs} parses this line at the semicolons; as a result, \cs{jsCodeForQzs}
+% expands to
+%\begin{verbatim}
+%var qz1=new Object();
+%var qz2=new Object();
+%var oQ1=new Object();
+%var sQ1=new Object();
+%\end{verbatim}
+% \begin{macrocode}
+\let\jsCodeForQzs\@empty\def\semiColon{;}\let\itsNonEmpty=0
+\def\jsForQzs#1\@nil{\jsForQzsi#1;;\@nil}
+\def\jsForQzsi#1;#2\@nil{\def\argii{#2}\ifx\argii\semiColon
+ \let\eqs@next\relax\else
+ \let\itsNonEmpty=1%
+ \g@addto@macro\jsCodeForQzs{var #1=new Object();^^J}%
+ \def\eqs@next{\jsForQzsi#2\@nil}\fi\eqs@next}
+% \end{macrocode}
+% We input the file that is created at the end of the document. We do a \cs{AtEndOfPackage} because
+% the command \cs{jsCodeForQzs} must be well defined by the time the document JavaScript are inserted.
+% \begin{macrocode}
+\AtEndOfPackage{\InputIfFileExists{qzlist-\jobname.cut}{}{}}
+% \end{macrocode}
+% At the end of the document after all quizzes and shortquizzes are known, we save them to
+% the file \texttt{qzlist-\string\jobname.cut}, they are then input in the preamble.
+% The \DescribeMacro{\saveListofQzs}\cs{saveListofQzs} writes the name of each quiz to an
+% semi-colon delimited list.
+% \begin{macrocode}
+\let\jsForQzsHold\@empty
+\let\cListOfQuizNames\@empty
+\let\cListOfSQuizNames\@empty
+\let\eqsHandleOpen=0
+\def\saveListofQzs{%
+ \ifx\ListOfQuizNames\@empty\else
+ \let\jsForQzsHold\@empty
+ \let\cListOfQuizNames\@empty
+ \edef\ListOfQuizNames{\expandafter\@gobble\ListOfQuizNames}
+ \immediate\openout\CommentStream=qzlist-\jobname.cut
+ \let\eqsHandleOpen=1
+ \expandafter\@for\expandafter
+ \@qz\expandafter:\expandafter=\ListOfQuizNames\do{%
+ \edef\@tmpExp{\noexpand
+ \g@addto@macro\noexpand\jsForQzsHold{\@qz;}}\@tmpExp
+ \edef\@tmpExp{\noexpand
+ \g@addto@macro\noexpand\cListOfQuizNames{,"\@qz"}}\@tmpExp
+ }%
+ \fi
+ \ifx\ListOfSQuizNames\@empty\else
+ \if\eqsHandleOpen0
+ \let\jsForQzsHold\@empty
+ \immediate\openout\CommentStream=qzlist-\jobname.cut
+ \let\eqsHandleOpen=1\fi
+ \let\cListOfSQuizNames\@empty
+ \edef\ListOfSQuizNames{\expandafter\@gobble\ListOfSQuizNames}
+ \expandafter\@for\expandafter\@qz
+ \expandafter:\expandafter=\ListOfSQuizNames\do{%
+ \edef\@tmpExp{\noexpand\g@addto@macro\noexpand
+ \jsForQzsHold{\@qz;}}\@tmpExp
+ \edef\@tmpExp{\noexpand
+ \g@addto@macro\noexpand\cListOfSQuizNames{,"\@qz"}}\@tmpExp
+ }%
+ \immediate\write\CommentStream{%
+ \string\jsForQzs\space\jsForQzsHold\string\@nil}
+ \fi
+ \if\eqsHandleOpen1
+ \ifx\ListOfQuizNames\@empty\else
+ \immediate\write\CommentStream{%
+ \string\def\string\cListOfQuizNames{\expandafter
+ \@gobble\cListOfQuizNames}}
+ \fi
+ \ifx\ListOfSQuizNames\@empty\else
+ \immediate\write\CommentStream{%
+ \string\def\string\cListOfSQuizNames{\expandafter
+ \@gobble\cListOfSQuizNames}}
+ \fi
+ \fi
+}
+% \end{macrocode}
+% Expand \cs{saveListofQzs} at the end of the document.
+% \begin{macrocode}
+\AtEndDocument{\saveListofQzs}
+% \end{macrocode}
+% \section{Document JavaScript}
+% \begin{macrocode}
+\dlJSStr{\eqerrUnfinishQuizAtSave}
+ {One of your quizzes is not finished, you will lose those responses.}
+\begin{insDLJS}{gcnt}{eq-save: Save and Resume JS support}
+var _passToQuestions=false;
+var oRecordOfQuizData;
+var _docDevMode=\devMode;
+var aQzList=new Array(\cListOfQuizNames);
+var aSqList=new Array(\cListOfSQuizNames);
+\jsCodeForQzs%
+cntCorrectResponses.nCorrectInDoc=0;
+cntCorrectResponses.nOutOfInDoc=0;
+cntCorrectResponses.nPtsCorrectInDoc=0;
+cntCorrectResponses.nPtsOutOfInDoc=0;
+% \end{macrocode}
+%\leavevmode\IndexJS{cntCorrectResponses()}is the workhorse of \pkg{eq-save}. It keeps tabs on the
+%total number of correct answers and the total number of questions. All \env{shortquiz}es are known immediately,
+%but results from \env{quiz} environments are not known until the student presses the `End Quiz' button.
+% \begin{macrocode}
+function cntCorrectResponses() {
+ var f=this.getField("\eqsroot");
+ if (f==null) return;
+ var g=f.getArray();
+% \end{macrocode}
+% \textbf{Naming convention:}\\\null\qquad\texttt{\string\eqsroot.ScoreComb},
+% \texttt{\string\eqsroot.Score}, \texttt{\string\eqsroot.OutOf}\\[3pt]
+% It is expected that the length \texttt{g.length=1\string|2\string|3}\\\null\quad
+% if \texttt{g.length=1}, we expect the field to be \texttt{\string\eqsroot.ScoreComb},\\\null\quad
+% if \texttt{g.length=2}, we expect \texttt{\string\eqsroot.Score}
+% and \texttt{\string\eqsroot.OutOf}, and\\\null\quad
+% if \texttt{g.length=3}, report all three
+% \begin{macrocode}
+ var fld1="\eqsroot.Score";
+ var fld2="\eqsroot.OutOf";
+ var fld3="\eqsroot.ScoreComb";
+ var fld4="\eqsroot.ptScore";
+ var fld5="\eqsroot.ptOutOf";
+ var fld6="\eqsroot.ptScoreComb";
+ cntCorrectResponses.nCorrectInDoc=0;
+ cntCorrectResponses.nOutOfInDoc=0;
+ cntCorrectResponses.nPtsCorrectInDoc=0;
+ cntCorrectResponses.nPtsOutOfInDoc=0;
+ var pos,baseName;
+ for (var i=0; i<this.numFields; i++) {
+ fname=this.getNthFieldName(i);
+ baseName=fname+"..";
+ pos=baseName.indexOf(".");
+ baseName=baseName.substring(pos+1);
+ pos=baseName.indexOf(".");
+ baseName=baseName.substring(0,pos);
+ if (aQzList.indexOf(baseName)!=-1) {
+ continue;
+ }
+ pos=fname.indexOf(".");
+ var root=fname.substring(0,pos);
+ if (root=="obj"|root=="grpobj") {
+ var f=this.getField(fname);
+% \end{macrocode}
+% Removing test for isCorrect, it can lead to some field not being
+% included when they should.
+% \changes{v1.1}{2018/04/07}{Removed test for isCorrect}
+% \begin{macrocode}
+% if (typeof f.isCorrect=="undefined") continue;
+ cntCorrectResponses.nOutOfInDoc+=1;
+ if (f.isCorrect==1) {
+ cntCorrectResponses.nCorrectInDoc+=1;
+ }
+ } else if (root=="mcq"||root=="mck"){
+ continue;
+ } else if (fname.substring(0,2)=="mc") {
+% \end{macrocode}
+% For MC within a quiz, there are two fields, name as indicated above.
+% if the second field exists, we ignore this field and continue.
+% \begin{macrocode}
+ var tst4qz="mcq"+fname.substring(2);
+ var otst4qz=this.getField(tst4qz);
+ if (otst4qz!=null)continue;
+% \end{macrocode}
+% Distinguish between multiple choice and multiple selection
+% \begin{macrocode}
+ var f=this.getField(fname);
+ var aResults=fname.match(/\./g);
+ if (aResults.length>2) {
+ // multiple selection
+ if (f.exportValues[0][0]==1) {
+ cntCorrectResponses.nOutOfInDoc+=1;
+ if (f.isBoxChecked(0)) {
+ cntCorrectResponses.nCorrectInDoc+=1;
+ }
+ }
+ } else {
+ // multiple choice
+ cntCorrectResponses.nOutOfInDoc+=1;
+ if (f.value[0]==1) {
+ cntCorrectResponses.nCorrectInDoc+=1;
+ }
+ }
+ }
+ }
+ addInQuizResults();
+% \end{macrocode}
+% We now display the totals results.
+% \begin{macrocode}
+ f=this.getField(fld1);
+ if(f!=null)f.value=cntCorrectResponses.nCorrectInDoc;
+ f=this.getField(fld2);
+ if(f!=null)f.value=cntCorrectResponses.nOutOfInDoc
+ var f=this.getField(fld3);
+ if (f!=null)f.value=(\dclScorePhse(cntCorrectResponses.nCorrectInDoc)%
+(cntCorrectResponses.nOutOfInDoc));
+ f=this.getField(fld4);
+ if(f!=null)f.value=cntCorrectResponses.nPtsCorrectInDoc;
+ f=this.getField(fld5);
+ if(f!=null)f.value=cntCorrectResponses.nPtsOutOfInDoc
+ var f=this.getField(fld6);
+ if (f!=null)
+ f.value=(\dclScorePhse(cntCorrectResponses.nPtsCorrectInDoc)%
+(cntCorrectResponses.nPtsOutOfInDoc));
+}
+% \end{macrocode}
+% \leavevmode\IndexJS{addInQuizResults()} is called by \texttt{cntCorrectResponses()} to add in the results
+% from the quizzes, if known. Because `Begin Quiz' and `End Quiz' can be links (not recommended) we save
+% the results of the quiz as the value of the field \texttt{ScoreData.\ameta{quizName}}. \pkg{exerquiz}
+% package save the quiz data in the form \texttt{"Score;\penalty0NQuestions;\penalty0ptScore;\penalty0NPointTotal"}.
+% This string can be split and the individual
+% values may be retrieved.
+% \begin{macrocode}
+function addInQuizResults() {
+ var results,value,score,outof;
+% \end{macrocode}
+% Coming into this function, the calculations so far are for \env{oQuestion} and \env{shortquiz} environments, these normally
+% don't have points assigned, and we do not support them if they do. Instead, we'll assign them to the points
+% \begin{macrocode}
+ cntCorrectResponses.nPtsCorrectInDoc=%
+cntCorrectResponses.nCorrectInDoc;
+ cntCorrectResponses.nPtsOutOfInDoc=cntCorrectResponses.nOutOfInDoc;
+ for (var i=0; i<aQzList.length; i++) {
+ var f=this.getField("ScoreData."+aQzList[i]);
+ if (f!=null) {
+ if (f.value!="") {
+ aTmp=f.value.split(";");
+ cntCorrectResponses.nCorrectInDoc+=(1*aTmp[0]);
+ cntCorrectResponses.nOutOfInDoc+=(1*aTmp[1]);
+ cntCorrectResponses.nPtsCorrectInDoc+=(1*aTmp[2]);
+ cntCorrectResponses.nPtsOutOfInDoc+=(1*aTmp[3]);
+ }
+ }
+ }
+}
+% \end{macrocode}
+% \leavevmode\IndexJS{clearAllSQElements()} clears all the quiz fields (all types). Much of the code
+% here is copied from \pkg{exerquiz}.
+% \begin{macrocode}
+function clearAllSQElements() {
+ var fname;
+ // clear any short quizzes and any supportive elements
+ for (var i=0; i<aSqList.length; i++) {
+ ProcessIt = false;
+ if ( typeof eval(aSqList[i])== "undefined" )
+ eval(aSqList[i])= new Object();
+ if (typeof appAlerts[aSqList[i]] == "undefined")
+ appAlerts[aSqList[i]] = new Object();
+ this.resetForm(new Array("mc."+aSqList[i],"obj."+aSqList[i],%
+"tally."+aSqList[i],"grpobj."+aSqList[i]));
+ var f = this.getField("obj."+aSqList[i]);
+ if ( f != null ) f.strokeColor=\ifx\defaultColorJSLoc\@empty%
+\defaultColorJS\else\defaultColorJSLoc\fi;
+ f = this.getField("grpobj."+aSqList[i]);
+ if ( f != null ) f.strokeColor=\ifx\defaultColorJSLoc\@empty%
+\defaultColorJS\else\defaultColorJSLoc\fi;
+ f = this.getField("rbmarkup."+aSqList[i]);
+ if ( f != null ) f.display=display.hidden;
+ eval(aSqList[i]).Grp = {};
+ appAlerts[aSqList[i]].bAfterValue=false;
+ ProcessIt=true;
+ }
+ isAQuizUnfinished.check=true;
+ // clear any quizzes and any supportive elements
+ for (var i=0; i<aQzList.length; i++) {
+ InitializeQuiz(aQzList[i],1);
+ aQuizControl[aQzList[i]] = 0;
+ }
+% \end{macrocode}
+% Here's where we clear all the field with parent names of
+% \cs{eqsroot} (\texttt{SUMRY}), \texttt{holdScoreData}, and \texttt{ScoreData}.
+% \begin{macrocode}
+ this.resetForm(["\eqsroot","holdScoreData","ScoreData"]);
+ oRecordOfQuizData=new Object();
+}
+% \end{macrocode}
+% \leavevmode\IndexJS{chk4PassToQuestions()} This function is used in the keystroke and format
+% phase of the \cs{nameField} command. If the student/user clears the field or changes the value
+% of the field once it has been committed, \texttt{chk4PassToQuestions()} then calls \texttt{clearAllSQElements()}
+% to clear all fields.
+% \begin{macrocode}
+chk4PassToQuestions.entered=false;
+function chk4PassToQuestions(event) {
+ if(event.willCommit) {
+ if (chk4PassToQuestions.entered) {
+ _passToQuestions=false;
+ clearAllSQElements();
+ this.dirty=false;
+ return;
+ }
+ if(event.value!="") {
+ var value=""+event.value;
+ value = value.replace(/\s/g,"");
+ if(value==null || value.length==0) {
+ _passToQuestions=false;
+ chk4PassToQuestions.entered=false;
+ } else {
+ _passToQuestions=true;
+ chk4PassToQuestions.entered=true;
+ clearAllSQElements();
+ this.dirty=false;
+ }
+ }
+ }
+}
+% \end{macrocode}
+% \leavevmode\IndexJS{collectQuizData()} is called by the \texttt{willSave} event. It save
+% the object \texttt{oRecordOfQuizData} to the field \texttt{holdScoreData} as a string.
+% \begin{macrocode}
+function collectQuizData() {
+ var f=this.getField("holdScoreData");
+ f.value=(oRecordOfQuizData.toSource());
+}
+% \end{macrocode}
+% \leavevmode\IndexJS{restoreQuizData()} is called when the document is opened and attempts to
+% transfer the value of \texttt{holdScoreData} back into \texttt{oRecordOfQuizData}.
+% \begin{macrocode}
+restoreQuizData.hasRestoredData=false;
+function restoreQuizData() {
+ var f=this.getField("holdScoreData");
+ try{oRecordOfQuizData=eval(f.value);}catch(e){return;}
+ for (fname in oRecordOfQuizData) {
+ f=this.getField(fname);
+ if (typeof oRecordOfQuizData[fname]=="object") {
+ // name of field is endQuiz.qzname
+ var pos=fname.indexOf(".");
+ var qzName=fname.substring(pos+1);
+ lstOfQuizzes[qzName]=eval(qzName);
+ Score=1*oRecordOfQuizData[fname][0];
+ NQuestions=1*oRecordOfQuizData[fname][1];
+ ptScore=1*oRecordOfQuizData[fname][2];
+ NPointTotal=1*oRecordOfQuizData[fname][3];
+ var h=this.getField("ScoreData."+qzName);
+ h.value=Score+";"+NQuestions+";"+ptScore+";"+NPointTotal;
+ } else f.isCorrect=oRecordOfQuizData[fname];
+ }
+}
+% \end{macrocode}
+% \leavevmode\IndexJS{IhrNameFormat()} is the format script for the \cs{nameField} command.
+% \begin{macrocode}
+function IhrNameFormat(event){
+ if(event.value!="") {
+ var value=""+event.value;
+ value = value.replace(/\s/g,"");
+ if(value==null || value.length==0) {
+ _passToQuestions=false;
+ chk4PassToQuestions.entered=false;
+ } else {
+ _passToQuestions=true;
+ chk4PassToQuestions.entered=true;
+ this.dirty=false;
+ }
+ } else {
+ chk4PassToQuestions.entered=false;
+ _passToQuestions=false;
+ }
+}
+% \end{macrocode}
+% \leavevmode\IndexJS{isAQuizUnfinishedAtSave()} is a variation on the JavaScript function
+% \texttt{isAQuizUnfinished} defined in \pkg{exerquiz}. When there is an unfinished quiz
+% and the user saves the document, this function (call by \texttt{willSave}) warns the user
+% that he will lose the answer entered into the quiz. It is too late to stop the save, there
+% is no JavaScript command for doing that.
+% \begin{macrocode}
+function isAQuizUnfinishedAtSave()
+{
+ for ( var qtfield in aQuizControl )
+ if ( aQuizControl[qtfield] == 1 )
+ {
+ eqAppAlert(\eqerrUnfinishQuizAtSave, 3);
+ return false;
+ }
+ return true;
+}
+\end{insDLJS}
+% \end{macrocode}
+% \begin{macrocode}
+\ap@restoreCats
+%</package>
+% \end{macrocode}
+\endinput
diff --git a/texmf-dist/source/latex/eq-save/eq-save.ins b/texmf-dist/source/latex/eq-save/eq-save.ins
new file mode 100644
index 00000000..6f4531a0
--- /dev/null
+++ b/texmf-dist/source/latex/eq-save/eq-save.ins
@@ -0,0 +1,60 @@
+%%
+%% This file will generate fast loadable files and documentation
+%% driver files from the doc files in this package when run through
+%% LaTeX or TeX.
+%%
+%% Copyright 1999-2016 D. P. Story
+%%
+%% This file is part of the `AcroTeX eDucation Bundle'.
+%% -------------------------------------------
+%%
+%% It may be distributed under the conditions of the LaTeX Project Public
+%% License, either version 1.2 of this license or (at your option) any
+%% later version. The latest version of this license is in
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.2 or later is part of all distributions of LaTeX
+%% version 1999/12/01 or later.
+%%
+%% --------------- start of docstrip commands ------------------
+%%
+\def\filedate{2017/07/29}
+\def\batchfile{eq-save.ins}
+
+\input docstrip
+\ifx\generate\undefined
+ \Msg{**********************************************}
+ \Msg{*}
+ \Msg{* This installation requires docstrip}
+ \Msg{* version 2.4 or later.}
+ \Msg{*}
+ \Msg{* An older version of docstrip has been input}
+ \Msg{*}
+ \Msg{**********************************************}
+ \errhelp{Move or rename old docstrip.tex and get a newer one.}
+ \errmessage{Old docstrip in input path}
+ \batchmode
+ \csname @@end\endcsname\end
+\fi
+
+\keepsilent
+\askforoverwritefalse
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\preamble
+\endpreamble
+
+\generate
+{%
+ \file{eq-save.sty}{\from{eq-save.dtx}{copyright,package}}
+}
+
+\Msg{***************************************************************}
+\Msg{*}
+\Msg{* \space To finish the installation you have to copy the files }
+\Msg{*}
+\Msg{* \space *.sty, *.cfg and *.def into a directory searched by TeX}
+\Msg{*}
+\Msg{***************************************************************}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\endinput
diff --git a/texmf-dist/tex/latex/eq-save/eq-save.sty b/texmf-dist/tex/latex/eq-save/eq-save.sty
new file mode 100644
index 00000000..8bbaee95
--- /dev/null
+++ b/texmf-dist/tex/latex/eq-save/eq-save.sty
@@ -0,0 +1,384 @@
+%%
+%% This is file `eq-save.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% eq-save.dtx (with options: `copyright,package')
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% eq-save package, %%
+%% Copyright (C) 2017-2018 %%
+%% dpstory@uakron.edu %%
+%% %%
+%% This program can redistributed and/or modified under %%
+%% the terms of the LaTeX Project Public License %%
+%% Distributed from CTAN archives in directory %%
+%% macros/latex/base/lppl.txt; either version 1.2 of %%
+%% the License, or (at your option) any later version. %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\NeedsTeXFormat{LaTeX2e}[1997/12/01]
+\ProvidesPackage{eq-save}
+ [2018/04/07 v1.1 eq-save: save exerquiz quizzes and resume (dps)]
+\DeclareOption{devmode}{\def\devMode{true}}
+\DeclareOption{!devmode}{\def\devMode{false}}
+\def\devMode{false}
+\ProcessOptions
+\RequirePackage{exerquiz}[2017/07/30]
+\RequirePackage{atbegshi}
+\edef\ap@restoreCats{%
+ \catcode`\noexpand\"=\the\catcode`\"\relax
+ \catcode`\noexpand\,=\the\catcode`\,\relax
+ \catcode`\noexpand\(=\the\catcode`\(\relax
+ \catcode`\noexpand\!=\the\catcode`\!\relax
+}
+\@makeother\"\@makeother\,\@makeother\(\@makeother\!
+\newcommand\nameField[4][]{\textField[#1
+ \AAkeystroke{chk4PassToQuestions(event);}
+ \AAformat{if(typeof oRecordOfQuizData=="undefined") \r\t
+ var oRecordOfQuizData=new Object();\r
+ try{IhrNameFormat(event);}catch(e){}
+ }]{#2}{#3}{#4}}
+\newcommand{\hiddenScoreData}{\makebox[0pt][l]{%
+\textField[\F\FHidden\V{({})}\DV{({})}\AAformat{%
+ if(typeof oRecordOfQuizData=="undefined")\r\t
+ oRecordOfQuizData={};}\BG{}\BC{}]{holdScoreData}{0bp}{0bp}}}
+\AtBeginShipoutFirst{\hiddenScoreData}
+\newcommand{\sField}[3][]{\textField[\Ff{\FfReadOnly}#1]%
+ {\eqsroot.Score}{#2}{#3}}
+\newcommand{\ooField}[3][]{\textField[\Ff{\FfReadOnly}#1]%
+ {\eqsroot.OutOf}{#2}{#3}}
+\newcommand{\sooField}[3][]{\textField[\Ff{\FfReadOnly}#1]%
+ {\eqsroot.ScoreComb}{#2}{#3}}
+\newcommand{\psField}[3][]{\textField[\Ff{\FfReadOnly}#1]%
+ {\eqsroot.ptScore}{#2}{#3}}
+\newcommand{\pooField}[3][]{\textField[\Ff{\FfReadOnly}#1]%
+ {\eqsroot.ptOutOf}{#2}{#3}}
+\newcommand{\psooField}[3][]{\textField[\Ff{\FfReadOnly}#1]%
+ {\eqsroot.ptScoreComb}{#2}{#3}}
+\newcommand{\clearAllField}[3][]{\pushButton[\CA{Clear All}#1
+ \AAmouseup{clearAllSQElements();}]{globalClearAll}{#2}{#3}}
+\newcommand{\eqsSetActionKeys}{%
+ \setActionKeys{%
+ \AddAAKeystroke{\if\eqQuizType\isSQZ
+ event.target.isCorrect=(retn)?1:0;\r\t
+ oRecordOfQuizData[event.target.name]=event.target.isCorrect;\r\t
+ cntCorrectResponses();\fi}
+ \AddAAMouseUpMC{\if\eqQuizType\isSQZ
+ event.target.isCorrect=\Ans@choice;\r
+ oRecordOfQuizData[event.target.name]=event.target.isCorrect;\r
+ cntCorrectResponses();\fi}
+ \AddAAMouseUpMS{\if\eqQuizType\isSQZ
+ event.target.isCorrect=\Ans@choice;\r
+ oRecordOfQuizData[event.target.name]=event.target.isCorrect;\r
+ cntCorrectResponses();\fi}
+ }%
+}
+\def\postInitQuiz{%
+ var f=this.getField("ScoreData.\oField");\r
+ f.value="0;0;0;0";\r
+ cntCorrectResponses();}
+\def\postSubmitQuiz{%
+ oRecordOfQuizData["ScoreData.\oField"]=%
+ [1*Score,1*NQuestions,1*ptScore,1*NPointTotal];\r\t\t
+ cntCorrectResponses();\r
+}
+\thisPageAction{\JS{if(!restoreQuizData.hasRestoredData)\r\t
+ var rqdTO=(app.setTimeOut("restoreQuizData();app.clearTimeOut(rqdTO);%
+ restoreQuizData.hasRestoredData=true",1000));}}{}
+\begin{willSave}
+isAQuizUnfinishedAtSave();
+if (typeof oRecordOfQuizData !="undefined") collectQuizData();
+\end{willSave}
+\flJSStr[noquotes,noparens]{\EnterNameFirstMsg}{You must enter
+ your name first!}
+\def\declareScorePhrase#1{\def\dclScorePhse(##1)(##2){#1}}
+\declareScorePhrase{#1+"\space\eqOutOf\space"+#2}
+\def\BeginNoPeeking{\def\IhrNamePO{\thisPageAction{%
+ \JS{if(!_docDevMode&&!_passToQuestions){\r\t
+ this.pageNum=0;\r\t
+ NoNameMsg=app.setTimeOut("app.alert('\EnterNameFirstMsg');%
+ app.clearTimeOut(NoNameMsg);",25);}}}{}}%
+ \IhrNamePO
+ \AtBeginShipout{\IhrNamePO}%
+}
+\newcommand{\DeclareReportRootName}[1]{\def\eqsroot{#1}%
+ \eqsSetActionKeys}
+\DeclareReportRootName{SUMRY}
+\@onlypreamble{\DeclareReportRootName}
+\let\jsCodeForQzs\@empty\def\semiColon{;}\let\itsNonEmpty=0
+\def\jsForQzs#1\@nil{\jsForQzsi#1;;\@nil}
+\def\jsForQzsi#1;#2\@nil{\def\argii{#2}\ifx\argii\semiColon
+ \let\eqs@next\relax\else
+ \let\itsNonEmpty=1%
+ \g@addto@macro\jsCodeForQzs{var #1=new Object();^^J}%
+ \def\eqs@next{\jsForQzsi#2\@nil}\fi\eqs@next}
+\AtEndOfPackage{\InputIfFileExists{qzlist-\jobname.cut}{}{}}
+\let\jsForQzsHold\@empty
+\let\cListOfQuizNames\@empty
+\let\cListOfSQuizNames\@empty
+\let\eqsHandleOpen=0
+\def\saveListofQzs{%
+ \ifx\ListOfQuizNames\@empty\else
+ \let\jsForQzsHold\@empty
+ \let\cListOfQuizNames\@empty
+ \edef\ListOfQuizNames{\expandafter\@gobble\ListOfQuizNames}
+ \immediate\openout\CommentStream=qzlist-\jobname.cut
+ \let\eqsHandleOpen=1
+ \expandafter\@for\expandafter
+ \@qz\expandafter:\expandafter=\ListOfQuizNames\do{%
+ \edef\@tmpExp{\noexpand
+ \g@addto@macro\noexpand\jsForQzsHold{\@qz;}}\@tmpExp
+ \edef\@tmpExp{\noexpand
+ \g@addto@macro\noexpand\cListOfQuizNames{,"\@qz"}}\@tmpExp
+ }%
+ \fi
+ \ifx\ListOfSQuizNames\@empty\else
+ \if\eqsHandleOpen0
+ \let\jsForQzsHold\@empty
+ \immediate\openout\CommentStream=qzlist-\jobname.cut
+ \let\eqsHandleOpen=1\fi
+ \let\cListOfSQuizNames\@empty
+ \edef\ListOfSQuizNames{\expandafter\@gobble\ListOfSQuizNames}
+ \expandafter\@for\expandafter\@qz
+ \expandafter:\expandafter=\ListOfSQuizNames\do{%
+ \edef\@tmpExp{\noexpand\g@addto@macro\noexpand
+ \jsForQzsHold{\@qz;}}\@tmpExp
+ \edef\@tmpExp{\noexpand
+ \g@addto@macro\noexpand\cListOfSQuizNames{,"\@qz"}}\@tmpExp
+ }%
+ \immediate\write\CommentStream{%
+ \string\jsForQzs\space\jsForQzsHold\string\@nil}
+ \fi
+ \if\eqsHandleOpen1
+ \ifx\ListOfQuizNames\@empty\else
+ \immediate\write\CommentStream{%
+ \string\def\string\cListOfQuizNames{\expandafter
+ \@gobble\cListOfQuizNames}}
+ \fi
+ \ifx\ListOfSQuizNames\@empty\else
+ \immediate\write\CommentStream{%
+ \string\def\string\cListOfSQuizNames{\expandafter
+ \@gobble\cListOfSQuizNames}}
+ \fi
+ \fi
+}
+\AtEndDocument{\saveListofQzs}
+\dlJSStr{\eqerrUnfinishQuizAtSave}
+ {One of your quizzes is not finished, you will lose those responses.}
+\begin{insDLJS}{gcnt}{eq-save: Save and Resume JS support}
+var _passToQuestions=false;
+var oRecordOfQuizData;
+var _docDevMode=\devMode;
+var aQzList=new Array(\cListOfQuizNames);
+var aSqList=new Array(\cListOfSQuizNames);
+\jsCodeForQzs%
+cntCorrectResponses.nCorrectInDoc=0;
+cntCorrectResponses.nOutOfInDoc=0;
+cntCorrectResponses.nPtsCorrectInDoc=0;
+cntCorrectResponses.nPtsOutOfInDoc=0;
+function cntCorrectResponses() {
+ var f=this.getField("\eqsroot");
+ if (f==null) return;
+ var g=f.getArray();
+ var fld1="\eqsroot.Score";
+ var fld2="\eqsroot.OutOf";
+ var fld3="\eqsroot.ScoreComb";
+ var fld4="\eqsroot.ptScore";
+ var fld5="\eqsroot.ptOutOf";
+ var fld6="\eqsroot.ptScoreComb";
+ cntCorrectResponses.nCorrectInDoc=0;
+ cntCorrectResponses.nOutOfInDoc=0;
+ cntCorrectResponses.nPtsCorrectInDoc=0;
+ cntCorrectResponses.nPtsOutOfInDoc=0;
+ var pos,baseName;
+ for (var i=0; i<this.numFields; i++) {
+ fname=this.getNthFieldName(i);
+ baseName=fname+"..";
+ pos=baseName.indexOf(".");
+ baseName=baseName.substring(pos+1);
+ pos=baseName.indexOf(".");
+ baseName=baseName.substring(0,pos);
+ if (aQzList.indexOf(baseName)!=-1) {
+ continue;
+ }
+ pos=fname.indexOf(".");
+ var root=fname.substring(0,pos);
+ if (root=="obj"|root=="grpobj") {
+ var f=this.getField(fname);
+ cntCorrectResponses.nOutOfInDoc+=1;
+ if (f.isCorrect==1) {
+ cntCorrectResponses.nCorrectInDoc+=1;
+ }
+ } else if (root=="mcq"||root=="mck"){
+ continue;
+ } else if (fname.substring(0,2)=="mc") {
+ var tst4qz="mcq"+fname.substring(2);
+ var otst4qz=this.getField(tst4qz);
+ if (otst4qz!=null)continue;
+ var f=this.getField(fname);
+ var aResults=fname.match(/\./g);
+ if (aResults.length>2) {
+ // multiple selection
+ if (f.exportValues[0][0]==1) {
+ cntCorrectResponses.nOutOfInDoc+=1;
+ if (f.isBoxChecked(0)) {
+ cntCorrectResponses.nCorrectInDoc+=1;
+ }
+ }
+ } else {
+ // multiple choice
+ cntCorrectResponses.nOutOfInDoc+=1;
+ if (f.value[0]==1) {
+ cntCorrectResponses.nCorrectInDoc+=1;
+ }
+ }
+ }
+ }
+ addInQuizResults();
+ f=this.getField(fld1);
+ if(f!=null)f.value=cntCorrectResponses.nCorrectInDoc;
+ f=this.getField(fld2);
+ if(f!=null)f.value=cntCorrectResponses.nOutOfInDoc
+ var f=this.getField(fld3);
+ if (f!=null)f.value=(\dclScorePhse(cntCorrectResponses.nCorrectInDoc)%
+(cntCorrectResponses.nOutOfInDoc));
+ f=this.getField(fld4);
+ if(f!=null)f.value=cntCorrectResponses.nPtsCorrectInDoc;
+ f=this.getField(fld5);
+ if(f!=null)f.value=cntCorrectResponses.nPtsOutOfInDoc
+ var f=this.getField(fld6);
+ if (f!=null)
+ f.value=(\dclScorePhse(cntCorrectResponses.nPtsCorrectInDoc)%
+(cntCorrectResponses.nPtsOutOfInDoc));
+}
+function addInQuizResults() {
+ var results,value,score,outof;
+ cntCorrectResponses.nPtsCorrectInDoc=%
+cntCorrectResponses.nCorrectInDoc;
+ cntCorrectResponses.nPtsOutOfInDoc=cntCorrectResponses.nOutOfInDoc;
+ for (var i=0; i<aQzList.length; i++) {
+ var f=this.getField("ScoreData."+aQzList[i]);
+ if (f!=null) {
+ if (f.value!="") {
+ aTmp=f.value.split(";");
+ cntCorrectResponses.nCorrectInDoc+=(1*aTmp[0]);
+ cntCorrectResponses.nOutOfInDoc+=(1*aTmp[1]);
+ cntCorrectResponses.nPtsCorrectInDoc+=(1*aTmp[2]);
+ cntCorrectResponses.nPtsOutOfInDoc+=(1*aTmp[3]);
+ }
+ }
+ }
+}
+function clearAllSQElements() {
+ var fname;
+ // clear any short quizzes and any supportive elements
+ for (var i=0; i<aSqList.length; i++) {
+ ProcessIt = false;
+ if ( typeof eval(aSqList[i])== "undefined" )
+ eval(aSqList[i])= new Object();
+ if (typeof appAlerts[aSqList[i]] == "undefined")
+ appAlerts[aSqList[i]] = new Object();
+ this.resetForm(new Array("mc."+aSqList[i],"obj."+aSqList[i],%
+"tally."+aSqList[i],"grpobj."+aSqList[i]));
+ var f = this.getField("obj."+aSqList[i]);
+ if ( f != null ) f.strokeColor=\ifx\defaultColorJSLoc\@empty%
+\defaultColorJS\else\defaultColorJSLoc\fi;
+ f = this.getField("grpobj."+aSqList[i]);
+ if ( f != null ) f.strokeColor=\ifx\defaultColorJSLoc\@empty%
+\defaultColorJS\else\defaultColorJSLoc\fi;
+ f = this.getField("rbmarkup."+aSqList[i]);
+ if ( f != null ) f.display=display.hidden;
+ eval(aSqList[i]).Grp = {};
+ appAlerts[aSqList[i]].bAfterValue=false;
+ ProcessIt=true;
+ }
+ isAQuizUnfinished.check=true;
+ // clear any quizzes and any supportive elements
+ for (var i=0; i<aQzList.length; i++) {
+ InitializeQuiz(aQzList[i],1);
+ aQuizControl[aQzList[i]] = 0;
+ }
+ this.resetForm(["\eqsroot","holdScoreData","ScoreData"]);
+ oRecordOfQuizData=new Object();
+}
+chk4PassToQuestions.entered=false;
+function chk4PassToQuestions(event) {
+ if(event.willCommit) {
+ if (chk4PassToQuestions.entered) {
+ _passToQuestions=false;
+ clearAllSQElements();
+ this.dirty=false;
+ return;
+ }
+ if(event.value!="") {
+ var value=""+event.value;
+ value = value.replace(/\s/g,"");
+ if(value==null || value.length==0) {
+ _passToQuestions=false;
+ chk4PassToQuestions.entered=false;
+ } else {
+ _passToQuestions=true;
+ chk4PassToQuestions.entered=true;
+ clearAllSQElements();
+ this.dirty=false;
+ }
+ }
+ }
+}
+function collectQuizData() {
+ var f=this.getField("holdScoreData");
+ f.value=(oRecordOfQuizData.toSource());
+}
+restoreQuizData.hasRestoredData=false;
+function restoreQuizData() {
+ var f=this.getField("holdScoreData");
+ try{oRecordOfQuizData=eval(f.value);}catch(e){return;}
+ for (fname in oRecordOfQuizData) {
+ f=this.getField(fname);
+ if (typeof oRecordOfQuizData[fname]=="object") {
+ // name of field is endQuiz.qzname
+ var pos=fname.indexOf(".");
+ var qzName=fname.substring(pos+1);
+ lstOfQuizzes[qzName]=eval(qzName);
+ Score=1*oRecordOfQuizData[fname][0];
+ NQuestions=1*oRecordOfQuizData[fname][1];
+ ptScore=1*oRecordOfQuizData[fname][2];
+ NPointTotal=1*oRecordOfQuizData[fname][3];
+ var h=this.getField("ScoreData."+qzName);
+ h.value=Score+";"+NQuestions+";"+ptScore+";"+NPointTotal;
+ } else f.isCorrect=oRecordOfQuizData[fname];
+ }
+}
+function IhrNameFormat(event){
+ if(event.value!="") {
+ var value=""+event.value;
+ value = value.replace(/\s/g,"");
+ if(value==null || value.length==0) {
+ _passToQuestions=false;
+ chk4PassToQuestions.entered=false;
+ } else {
+ _passToQuestions=true;
+ chk4PassToQuestions.entered=true;
+ this.dirty=false;
+ }
+ } else {
+ chk4PassToQuestions.entered=false;
+ _passToQuestions=false;
+ }
+}
+function isAQuizUnfinishedAtSave()
+{
+ for ( var qtfield in aQuizControl )
+ if ( aQuizControl[qtfield] == 1 )
+ {
+ eqAppAlert(\eqerrUnfinishQuizAtSave, 3);
+ return false;
+ }
+ return true;
+}
+\end{insDLJS}
+\ap@restoreCats
+\endinput
+%%
+%% End of file `eq-save.sty'.
diff --git a/tlpkg/tlpsrc/eq-save.tlpsrc b/tlpkg/tlpsrc/eq-save.tlpsrc
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/tlpkg/tlpsrc/eq-save.tlpsrc