Skip to content
This repository was archived by the owner on Jun 7, 2023. It is now read-only.

Commit 36d2112

Browse files
committed
Fixes to timed exams.
Changed the start button to green. Changed the arrows for next and previous to single arrows. Moved the next and previous arrows to below the question. Moved the question number jump buttons to below the next and previous buttons. Updated the results to include the question numbers.
1 parent 574cb2e commit 36d2112

File tree

3 files changed

+132
-57
lines changed

3 files changed

+132
-57
lines changed

runestone/assess/css/bootstrap.min.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

runestone/assess/js/timed.js

Lines changed: 130 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ Timed.prototype.init = function (opts) {
5757
this.taken = 0;
5858
this.score = 0;
5959
this.incorrect = 0;
60+
this.correctStr = "";
61+
this.incorrectStr = "";
62+
this.skippedStr = "";
6063
this.skipped = 0;
6164

6265
this.currentQuestionIndex = 0; // Which question is currently displaying on the page
@@ -90,6 +93,12 @@ Timed.prototype.renderTimedAssess = function () {
9093

9194
// Replace intermediate HTML with rendered HTML
9295
$(this.origElem).replaceWith(this.assessDiv);
96+
97+
// check if already taken and if so show results
98+
this.tookTimedExam();
99+
if (this.taken) {
100+
this.handlePrevAssessment();
101+
}
93102
};
94103

95104
Timed.prototype.renderContainer = function () {
@@ -98,9 +107,9 @@ Timed.prototype.renderContainer = function () {
98107
this.timedDiv = document.createElement("div"); // div that will hold the questions for the timed assessment
99108
this.navDiv = document.createElement("div"); // For navigation control
100109
$(this.navDiv).attr({"style": "text-align:center"});
101-
this.timedDiv.appendChild(this.navDiv);
102110
this.switchDiv = document.createElement("div"); // is replaced by the questions
103111
this.timedDiv.appendChild(this.switchDiv);
112+
this.timedDiv.appendChild(this.navDiv);
104113
$(this.timedDiv).attr({ // set the id, and style the div to be hidden
105114
"id": "timed_Test",
106115
"style": "display:none"
@@ -113,6 +122,7 @@ Timed.prototype.renderTimer = function () {
113122
this.wrapperDiv.id = "startWrapper";
114123
this.timerContainer.id = "output";
115124
this.wrapperDiv.appendChild(this.timerContainer);
125+
this.showTime();
116126
};
117127

118128
Timed.prototype.renderControlButtons = function () {
@@ -124,7 +134,7 @@ Timed.prototype.renderControlButtons = function () {
124134
this.startBtn = document.createElement("btn");
125135
this.pauseBtn = document.createElement("btn");
126136
$(this.startBtn).attr({
127-
"class": "btn btn-default",
137+
"class": "btn btn-success",
128138
"id": "start"
129139
});
130140
this.startBtn.textContent = "Start";
@@ -145,13 +155,15 @@ Timed.prototype.renderControlButtons = function () {
145155
this.assessDiv.appendChild(this.wrapperDiv);
146156
this.assessDiv.appendChild(this.controlDiv);
147157
};
158+
159+
148160
Timed.prototype.renderNavControls = function () {
149-
var _this = this;
161+
_this = this;
150162
this.pagNavList = document.createElement("ul");
151163
$(this.pagNavList).addClass("pagination");
152164
this.leftContainer = document.createElement("li");
153165
this.leftNavButton = document.createElement("a");
154-
this.leftNavButton.innerHTML = "&laquo";
166+
this.leftNavButton.innerHTML = "‹ Prev";
155167
$(this.leftNavButton).attr("aria-label", "Previous");
156168
$(this.leftNavButton).css("cursor", "pointer");
157169
this.leftNavButton.addEventListener("click", function () {
@@ -161,37 +173,17 @@ Timed.prototype.renderNavControls = function () {
161173
this.currentQuestionIndex--;
162174
this.renderTimedQuestion();
163175
this.ensureButtonSafety();
164-
for (var i = 0; i < _this.pagNavList.childNodes.length; i++) {
165-
$(this.pagNavList.childNodes[i]).removeClass("active");
176+
for (var i = 0; i < this.qNumList.childNodes.length; i++) {
177+
$(this.qNumList.childNodes[i]).removeClass("active");
166178
}
167-
$(this.pagNavList.childNodes[this.currentQuestionIndex + 1]).addClass("active");
179+
$(this.qNumList.childNodes[this.currentQuestionIndex]).addClass("active");
168180
}.bind(this), false);
169181
this.leftContainer.appendChild(this.leftNavButton);
170182
this.pagNavList.appendChild(this.leftContainer);
171-
for (var i = 0; i < this.renderedQuestionArray.length; i++) {
172-
var tmpLi = document.createElement("li");
173-
var tmpA = document.createElement("a");
174-
tmpA.innerHTML = i + 1;
175-
$(tmpA).css("cursor", "pointer");
176-
if (i === 0) {
177-
$(tmpLi).addClass("active");
178-
}
179-
tmpA.onclick = function () {
180-
_this.currentQuestionIndex = this.innerHTML - 1;
181-
_this.renderTimedQuestion();
182-
_this.ensureButtonSafety();
183-
for (var i = 0; i < _this.pagNavList.childNodes.length; i++) {
184-
$(_this.pagNavList.childNodes[i]).removeClass("active");
185-
}
186-
$(this.parentNode).addClass("active");
187-
};
188-
tmpLi.appendChild(tmpA);
189-
this.pagNavList.appendChild(tmpLi);
190-
}
191183
this.rightContainer = document.createElement("li");
192184
this.rightNavButton = document.createElement("a");
193185
$(this.rightNavButton).attr("aria-label", "Next");
194-
this.rightNavButton.innerHTML = "&raquo";
186+
this.rightNavButton.innerHTML = "Next &#8250;";
195187
$(this.rightNavButton).css("cursor", "pointer");
196188
this.rightNavButton.addEventListener("click", function () {
197189
if ($(this.rightContainer).hasClass("disabled")) {
@@ -200,17 +192,43 @@ Timed.prototype.renderNavControls = function () {
200192
this.currentQuestionIndex++;
201193
this.renderTimedQuestion();
202194
this.ensureButtonSafety();
203-
for (var i = 0; i < _this.pagNavList.childNodes.length; i++) {
204-
$(this.pagNavList.childNodes[i]).removeClass("active");
195+
for (var i = 0; i < this.qNumList.childNodes.length; i++) {
196+
$(this.qNumList.childNodes[i]).removeClass("active");
205197
}
206-
$(this.pagNavList.childNodes[this.currentQuestionIndex + 1]).addClass("active");
198+
$(this.qNumList.childNodes[this.currentQuestionIndex]).addClass("active");
207199
}.bind(this), false);
208200
this.rightContainer.appendChild(this.rightNavButton);
209201
this.pagNavList.appendChild(this.rightContainer);
210202
this.ensureButtonSafety();
211203
this.navDiv.appendChild(this.pagNavList);
204+
205+
// render the question number jump buttons
206+
this.qNumList = document.createElement("ul");
207+
$(this.qNumList).addClass("pagination");
208+
for (var i = 0; i < this.renderedQuestionArray.length; i++) {
209+
var tmpLi = document.createElement("li");
210+
var tmpA = document.createElement("a");
211+
tmpA.innerHTML = i + 1;
212+
$(tmpA).css("cursor", "pointer");
213+
if (i === 0) {
214+
$(tmpLi).addClass("active");
215+
}
216+
tmpA.onclick = function () {
217+
_this.currentQuestionIndex = this.innerHTML - 1;
218+
_this.renderTimedQuestion();
219+
_this.ensureButtonSafety();
220+
for (var i = 0; i < _this.qNumList.childNodes.length; i++) {
221+
$(_this.qNumList.childNodes[i]).removeClass("active");
222+
}
223+
$(this.parentNode).addClass("active");
224+
};
225+
tmpLi.appendChild(tmpA);
226+
this.qNumList.appendChild(tmpLi);
227+
}
228+
this.navDiv.appendChild(this.qNumList);
212229

213230
};
231+
214232
Timed.prototype.renderSubmitButton = function () {
215233
this.buttonContainer = document.createElement("div");
216234
$(this.buttonContainer).attr({"style": "text-align:center"});
@@ -219,7 +237,7 @@ Timed.prototype.renderSubmitButton = function () {
219237
"id": "finish",
220238
"class": "btn btn-inverse"
221239
});
222-
this.finishButton.textContent = "Submit answers";
240+
this.finishButton.textContent = "Submit Answers";
223241
this.finishButton.addEventListener("click", function () {
224242
this.finishAssessment();
225243
}.bind(this), false);
@@ -300,26 +318,32 @@ Timed.prototype.renderTimedQuestion = function () {
300318
=== Timer and control Functions ===
301319
=================================*/
302320

321+
Timed.prototype.handlePrevAssessment = function () {
322+
$(this.startBtn).hide();
323+
$(this.pauseBtn).attr("disabled", true);
324+
$(this.finishButton).attr("disabled", true);
325+
this.running = 0;
326+
this.done = 1;
327+
$(this.timedDiv).show();
328+
this.submitTimedProblems();
329+
}
330+
303331
Timed.prototype.startAssessment = function () {
332+
304333
this.tookTimedExam();
305334
if (!this.taken) {
306-
$(this.startBtn).attr("disabled", true);
335+
$(this.startBtn).hide();
307336
$(this.pauseBtn).attr("disabled", false);
308337
if (this.running === 0 && this.paused === 0) {
309338
this.running = 1;
310339
$(this.timedDiv).show();
311340
this.increment();
312341
this.logBookEvent({"event": "timedExam", "act": "start", "div_id": this.divid});
313-
localStorage.setItem(eBookConfig.email + ":" + this.divid, "started");
342+
var resultStr = "0; ;0; ;" + this.renderedQuestionArray.length +"; ;0";
343+
localStorage.setItem(eBookConfig.email + ":" + this.divid, resultStr);
314344
}
315345
} else {
316-
$(this.startBtn).attr("disabled", true);
317-
$(this.pauseBtn).attr("disabled", true);
318-
$(this.finishButton).attr("disabled", true);
319-
this.running = 0;
320-
this.done = 1;
321-
$(this.timedDiv).show();
322-
this.submitTimedProblems();
346+
this.handlePrevAssessment();
323347
}
324348
};
325349

@@ -413,7 +437,6 @@ Timed.prototype.checkIfFinished = function () {
413437
$(this.pauseBtn).attr("disabled", true);
414438
$(this.finishButton).attr("disabled", true);
415439
this.resetTimedMCMFStorage();
416-
//$(this.timedDiv).show();
417440
}
418441
};
419442

@@ -489,17 +512,32 @@ Timed.prototype.hideTimedFeedback = function () {
489512
};
490513

491514
Timed.prototype.checkScore = function () {
515+
this.correctStr = "";
516+
this.skippedStr = "";
517+
this.incorrectStr = "";
518+
492519
// Gets the score of each problem
493520
for (var i = 0; i < this.renderedQuestionArray.length; i++) {
494521
var correct = this.renderedQuestionArray[i].checkCorrectTimed();
495522
if (correct) {
496523
this.score++;
524+
this.correctStr = this.correctStr + (i + 1) + ", ";
497525
} else if (correct === null) {
498526
this.skipped++;
527+
this.skippedStr = this.skippedStr + (i + 1) + ", ";
499528
} else {
500529
this.incorrect++;
530+
this.incorrectStr = this.incorrectStr + (i + 1) + ", ";
501531
}
502532
}
533+
534+
// remove extra comma and space at end if any
535+
if (this.correctStr.length > 0) this.correctStr = this.correctStr.substring(0,this.correctStr.length-2);
536+
else this.correctStr = "None";
537+
if (this.skippedStr.length > 0) this.skippedStr = this.skippedStr.substring(0,this.skippedStr.length-2);
538+
else this.skippedStr = "None";
539+
if (this.incorrectStr.length > 0) this.incorrectStr = this.incorrectStr.substring(0,this.incorrectStr.length-2);
540+
else this.incorrectStr = "None";
503541
};
504542

505543
Timed.prototype.findTimeTaken = function () {
@@ -512,7 +550,7 @@ Timed.prototype.findTimeTaken = function () {
512550

513551
Timed.prototype.storeScore = function () {
514552
var storage_arr = [];
515-
storage_arr.push(this.score, this.incorrect, this.skipped, this.timeTaken);
553+
storage_arr.push(this.score, this.correctStr, this.incorrect, this.incorrectStr, this.skipped, this.skippedStr, this.timeTaken);
516554
localStorage.setItem(eBookConfig.email + ":" + this.divid, storage_arr.join(";"));
517555
};
518556

@@ -522,23 +560,60 @@ Timed.prototype.logScore = function () {
522560

523561
Timed.prototype.restoreFromStorage = function () {
524562
var tmpArr = localStorage.getItem(eBookConfig.email + ":" + this.divid).split(";");
525-
this.score = tmpArr[0];
526-
this.incorrect = tmpArr[1];
527-
this.skipped = tmpArr[2];
528-
this.timeTaken = tmpArr[3];
563+
if (tmpArr.length == 4)
564+
{
565+
this.score = tmpArr[0];
566+
this.incorrect = tmpArr[1];
567+
this.skipped = tmpArr[2];
568+
this.timeTaken = tmpArr[3];
569+
}
570+
else if (tmpArr.length == 7)
571+
{
572+
this.score = tmpArr[0];
573+
this.correctStr = tmpArr[1];
574+
this.incorrect = tmpArr[2];
575+
this.incorrectStr = tmpArr[3];
576+
this.skipped = tmpArr[4];
577+
this.skippedStr = tmpArr[5];
578+
this.timeTaken = tmpArr[6];
579+
}
580+
else {
581+
this.score = 0;
582+
this.incorrect = 0;
583+
this.skipped = this.renderedQuestionArray.length;
584+
this.timeTaken = 0;
585+
}
529586
this.displayScore();
530587
this.showTime();
531588
};
532589

533590
Timed.prototype.displayScore = function () {
534-
if (this.showResults) {
535-
var scoreString = "Num Correct: " + this.score + " Num Wrong: " + this.incorrect + " Num Skipped: " + this.skipped;
536-
var numQuestions = this.renderedQuestionArray.length;
537-
var percentCorrect = (this.score / numQuestions) * 100;
538-
scoreString += " Percent Correct: " + percentCorrect + "%";
539-
$(this.scoreDiv).text(scoreString);
540-
this.scoreDiv.style.display = "block";
541-
}
591+
if (this.showResults)
592+
{
593+
// If we have the list of
594+
if (this.correctStr.length > 0 || this.incorrectStr.length > 0 || this.skippedStr.length > 0)
595+
{
596+
var scoreString = "Num Correct: " + this.score + ". Questions: " + this.correctStr + "<br>" +
597+
"Num Wrong: " + this.incorrect + ". Questions: " + this.incorrectStr + "<br>" +
598+
"Num Skipped: " + this.skipped + ". Questions: " + this.skippedStr + "<br>";
599+
var numQuestions = this.renderedQuestionArray.length;
600+
var percentCorrect = (this.score / numQuestions) * 100;
601+
scoreString += "Percent Correct: " + percentCorrect + "%";
602+
$(this.scoreDiv).html(scoreString);
603+
this.scoreDiv.style.display = "block";
604+
}
605+
else
606+
{
607+
var scoreString = "Num Correct: " + this.score + "<br>" +
608+
"Num Wrong: " + this.incorrect + "<br>" +
609+
"Num Skipped: " + this.skipped + "<br>";
610+
var numQuestions = this.renderedQuestionArray.length;
611+
var percentCorrect = (this.score / numQuestions) * 100;
612+
scoreString += "Percent Correct: " + percentCorrect + "%";
613+
$(this.scoreDiv).html(scoreString);
614+
this.scoreDiv.style.display = "block";
615+
}
616+
}
542617
};
543618

544619
/*=======================================================

runestone/common/project_template/_templates/plugin_layouts/sphinx_bootstrap/static/bootstrap-3.0.0/css/bootstrap.min.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)