From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001
From: Norbert Preining <norbert@preining.info>
Date: Mon, 2 Sep 2019 13:46:59 +0900
Subject: Initial commit

---
 macros/latex/contrib/eq-save/eq-save.dtx | 646 +++++++++++++++++++++++++++++++
 1 file changed, 646 insertions(+)
 create mode 100644 macros/latex/contrib/eq-save/eq-save.dtx

(limited to 'macros/latex/contrib/eq-save/eq-save.dtx')

diff --git a/macros/latex/contrib/eq-save/eq-save.dtx b/macros/latex/contrib/eq-save/eq-save.dtx
new file mode 100644
index 0000000000..180d42fe67
--- /dev/null
+++ b/macros/latex/contrib/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
-- 
cgit v1.2.3

