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

Commit 235f260

Browse files
authored
Merge pull request #1218 from constantinol/flag
Addition of "Flag Question" button to timed exams
2 parents 7592a3e + 2f49451 commit 235f260

3 files changed

Lines changed: 87 additions & 2 deletions

File tree

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Declare files that must always have LF line endings on checkout so docker compose works on Windows
2+
* eol=lf

runestone/timed/css/timed.css

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,20 @@ ul#pageNums li {
1010
color: #000 !important;
1111
}
1212

13+
.flagBtn { /* documentation */
14+
background-color: #ED9C59 !important;
15+
border: 3px solid #CE5718;
16+
border-radius: 5px;
17+
color: #030201 !important;
18+
cursor: pointer;
19+
width: 150;
20+
height: 115;
21+
text-align: center;
22+
text-decoration: none;
23+
display: ruby;
24+
font-size: 15px;
25+
}
26+
1327
/* The following override styles in Bootstrap distribution file (bootstrap.min.css) */
1428

1529
.pagination > .active > a,
@@ -43,6 +57,12 @@ ul#pageNums li {
4357
color: #000;
4458
}
4559

60+
.pagination > .flagcolor > a,
61+
.pagination > .flagcolor > span {
62+
background-color: #ED9C59;
63+
color: #000;
64+
}
65+
4666
p.examwarning {
4767
width: 50%;
4868
margin-left: auto;

runestone/timed/js/timed.js

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,15 @@ export default class Timed extends RunestoneBase {
173173
$(this.navDiv).attr({
174174
style: "text-align:center",
175175
});
176+
this.flagDiv = document.createElement("div"); // div that will hold the "Flag Question" button
177+
$(this.flagDiv).attr({
178+
style: "text-align: center",
179+
});
176180
this.switchContainer = document.createElement("div");
177181
this.switchContainer.classList.add("switchcontainer");
178182
this.switchDiv = document.createElement("div"); // is replaced by the questions
179183
this.timedDiv.appendChild(this.navDiv);
184+
this.timedDiv.appendChild(this.flagDiv); // add flagDiv to timedDiv, which holds components for navigation and questions for timed assessment
180185
this.timedDiv.appendChild(this.switchContainer);
181186
this.switchContainer.appendChild(this.switchDiv);
182187
$(this.timedDiv).attr({
@@ -213,6 +218,7 @@ export default class Timed extends RunestoneBase {
213218
"click",
214219
async function () {
215220
$(this.finishButton).hide(); // hide the finish button for now
221+
$(this.flagButton).show();
216222
let mess = document.createElement("p");
217223
mess.innerHTML =
218224
"<strong>Warning: You will not be able to continue the exam if you close this tab, close the window, or navigate away from this page!</strong> Make sure you click the Finish Exam button when you are done to submit your work!";
@@ -249,6 +255,7 @@ export default class Timed extends RunestoneBase {
249255
}
250256

251257
renderNavControls() {
258+
// making "Prev" button
252259
this.pagNavList = document.createElement("ul");
253260
$(this.pagNavList).addClass("pagination");
254261
this.leftContainer = document.createElement("li");
@@ -261,6 +268,21 @@ export default class Timed extends RunestoneBase {
261268
$(this.leftNavButton).css("cursor", "pointer");
262269
this.leftContainer.appendChild(this.leftNavButton);
263270
this.pagNavList.appendChild(this.leftContainer);
271+
// making "Flag Question" button
272+
this.flaggingPlace = document.createElement("ul");
273+
$(this.flaggingPlace).addClass("pagination");
274+
this.flagContainer = document.createElement("li");
275+
this.flagButton = document.createElement("button");
276+
$(this.flagButton).addClass("flagBtn");
277+
this.flagButton.innerHTML = "Flag Question"; // name on button
278+
$(this.flagButton).attr("aria-labelledby", "Flag");
279+
$(this.flagButton).attr("tabindex", "5");
280+
$(this.flagButton).attr("role", "button");
281+
$(this.flagButton).attr("id", "flag");
282+
$(this.flagButton).css("cursor", "pointer");
283+
this.flagContainer.appendChild(this.flagButton); // adding button to container
284+
this.flaggingPlace.appendChild(this.flagContainer); // adding container to flaggingPlace
285+
// making "Next" button
264286
this.rightContainer = document.createElement("li");
265287
this.rightNavButton = document.createElement("button");
266288
$(this.rightNavButton).attr("aria-label", "Next");
@@ -273,6 +295,7 @@ export default class Timed extends RunestoneBase {
273295
this.pagNavList.appendChild(this.rightContainer);
274296
this.ensureButtonSafety();
275297
this.navDiv.appendChild(this.pagNavList);
298+
this.flagDiv.appendChild(this.flaggingPlace); // adds flaggingPlace to the flagDiv
276299
this.break = document.createElement("br");
277300
this.navDiv.appendChild(this.break);
278301
// render the question number jump buttons
@@ -295,6 +318,8 @@ export default class Timed extends RunestoneBase {
295318
this.qNumList.appendChild(this.qNumWrapperList);
296319
this.navDiv.appendChild(this.qNumList);
297320
this.navBtnListeners();
321+
this.flagBtnListener(); // listens for click on flag button
322+
$(this.flagButton).hide();
298323
}
299324

300325
// when moving off of a question in an active exam:
@@ -339,12 +364,12 @@ export default class Timed extends RunestoneBase {
339364
await this.navigateAway();
340365
}
341366
var target = $(event.target).text();
342-
if (target.match(/Next/)) {
367+
if (target.match(/Next/)) { // checks given text to match "Next"
343368
if ($(this.rightContainer).hasClass("disabled")) {
344369
return;
345370
}
346371
this.currentQuestionIndex++;
347-
} else if (target.match(/Prev/)) {
372+
} else if (target.match(/Prev/)) { // checks given text to match "Prev"
348373
if ($(this.leftContainer).hasClass("disabled")) {
349374
return;
350375
}
@@ -366,6 +391,27 @@ export default class Timed extends RunestoneBase {
366391
$(
367392
"ul#pageNums > ul > li:eq(" + this.currentQuestionIndex + ")"
368393
).addClass("active");
394+
if ($("ul#pageNums > ul > li:eq(" + this.currentQuestionIndex + ")"
395+
).hasClass("flagcolor")){ // checking for class
396+
this.flagButton.innerHTML = "Unflag Question"; // changes text on button
397+
}
398+
else{
399+
this.flagButton.innerHTML = "Flag Question"; // changes text on button
400+
}
401+
}
402+
403+
async handleFlag(event) {
404+
// called when flag button is clicked
405+
var target = $(event.target).text()
406+
if (target.match(/Flag Question/)) {
407+
$("ul#pageNums > ul > li:eq(" + this.currentQuestionIndex + ")"
408+
).addClass("flagcolor"); // class will change color of question block
409+
this.flagButton.innerHTML = "Unflag Question";
410+
} else {
411+
$("ul#pageNums > ul > li:eq(" + this.currentQuestionIndex + ")"
412+
).removeClass("flagcolor"); // will restore current color of question block
413+
this.flagButton.innerHTML = "Flag Question"; // also sets name back
414+
}
369415
}
370416

371417
async handleNumberedNav(event) {
@@ -394,6 +440,13 @@ export default class Timed extends RunestoneBase {
394440
$(
395441
"ul#pageNums > ul > li:eq(" + this.currentQuestionIndex + ")"
396442
).addClass("active");
443+
if ($("ul#pageNums > ul > li:eq(" + this.currentQuestionIndex + ")" // checking for flagcolor class
444+
).hasClass("flagcolor")){
445+
this.flagButton.innerHTML = "Unflag Question";
446+
}
447+
else{
448+
this.flagButton.innerHTML = "Flag Question";
449+
}
397450
await this.renderTimedQuestion();
398451
this.ensureButtonSafety();
399452
}
@@ -415,6 +468,15 @@ export default class Timed extends RunestoneBase {
415468
);
416469
}
417470

471+
// set up event for flag
472+
flagBtnListener() {
473+
this.flaggingPlace.addEventListener(
474+
"click",
475+
this.handleFlag.bind(this), // calls this to take action
476+
false
477+
);
478+
}
479+
418480
renderSubmitButton() {
419481
this.buttonContainer = document.createElement("div");
420482
$(this.buttonContainer).attr({
@@ -435,6 +497,7 @@ export default class Timed extends RunestoneBase {
435497
)
436498
) {
437499
await this.finishAssessment();
500+
$(this.flagButton).hide();
438501
}
439502
}.bind(this),
440503
false

0 commit comments

Comments
 (0)