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

Commit b7d74bb

Browse files
committed
Merge branch 'vqum-master'
2 parents 15761cd + cb3cc0a commit b7d74bb

3 files changed

Lines changed: 190 additions & 2 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.toggle-preview {
2+
border: 4px solid;
3+
border-radius: 10px;
4+
background-color: azure;
5+
padding-top: 10px;
6+
box-shadow: 10px 5px 5px gray;
7+
}

runestone/selectquestion/js/selectone.js

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
createTimedComponent,
99
} from "../../common/js/renderComponent";
1010
import RunestoneBase from "../../common/js/runestonebase";
11+
import "../css/selectquestion.css";
1112

1213
export default class SelectOne extends RunestoneBase {
1314
/**
@@ -38,6 +39,7 @@ export default class SelectOne extends RunestoneBase {
3839
this.selector_id = $(opts.orig).first().attr("id");
3940
this.primaryOnly = $(opts.orig).data("primary");
4041
this.ABExperiment = $(opts.orig).data("ab");
42+
this.toggle = $(opts.orig).data("toggle");
4143
opts.orig.id = this.selector_id;
4244
}
4345
/**
@@ -79,6 +81,9 @@ export default class SelectOne extends RunestoneBase {
7981
if (this.timedWrapper) {
8082
data.timedWrapper = this.timedWrapper;
8183
}
84+
if (this.toggle) {
85+
data.toggle = this.toggle;
86+
}
8287
let opts = this.origOpts;
8388
let selectorId = this.selector_id;
8489
console.log("getting question source");
@@ -116,14 +121,183 @@ export default class SelectOne extends RunestoneBase {
116121
self.containerDiv = res.question.containerDiv;
117122
self.realComponent.selectorId = selectorId;
118123
} else {
124+
///////////////////////////
125+
if (data.toggle) {
126+
var toggleQuestions = this.questions.split(", ");
127+
var toggleUI = "";
128+
if (!document.getElementById("component-preview")) {
129+
toggleUI +=
130+
'<div id="component-preview" class="col-md-6 toggle-preview" style="z-index: 999;"></div>';
131+
}
132+
toggleUI +=
133+
'<label for="' +
134+
selectorId +
135+
'-toggleQuestion" style="margin-left: 10px">Toggle Question:</label><select id="' +
136+
selectorId +
137+
'-toggleQuestion">';
138+
var i;
139+
var toggleQuestionHTMLSrc;
140+
var toggleQuestionSubstring;
141+
var toggleQuestionType;
142+
for (i = 0; i < toggleQuestions.length; i++) {
143+
toggleQuestionHTMLSrc = await this.getToggleSrc(
144+
toggleQuestions[i]
145+
);
146+
toggleQuestionSubstring = toggleQuestionHTMLSrc.split(
147+
'data-component="'
148+
)[1];
149+
switch (
150+
toggleQuestionSubstring.substring(
151+
0,
152+
toggleQuestionSubstring.indexOf('"')
153+
)
154+
) {
155+
case "activecode":
156+
toggleQuestionType = "Active Code";
157+
break;
158+
case "clickablearea":
159+
toggleQuestionType = "Clickable Area";
160+
break;
161+
case "dragndrop":
162+
toggleQuestionType = "Drag n Drop";
163+
break;
164+
case "fillintheblank":
165+
toggleQuestionType = "Fill in the Blank";
166+
break;
167+
case "multiplechoice":
168+
toggleQuestionType = "Multiple Choice";
169+
break;
170+
case "parsons":
171+
toggleQuestionType = "Parsons";
172+
break;
173+
case "shortanswer":
174+
toggleQuestionType = "Short Answer";
175+
break;
176+
}
177+
toggleUI +=
178+
'<option value="' +
179+
toggleQuestions[i] +
180+
'">' +
181+
toggleQuestionType +
182+
" - " +
183+
toggleQuestions[i] +
184+
"</option>";
185+
}
186+
toggleUI +=
187+
'</select><div id="' +
188+
selectorId +
189+
'-toggleSelectedQuestion">';
190+
var toggleFirstID = htmlsrc.split('id="')[1];
191+
toggleFirstID = toggleFirstID.split('"')[0];
192+
htmlsrc = toggleUI + htmlsrc + "</div>";
193+
}
194+
///////////////////////////
119195
// just render this component on the page in its usual place
120196
res = renderRunestoneComponent(htmlsrc, selectorId, {
121197
selector_id: selectorId,
122198
useRunestoneServices: true,
123199
});
200+
///////////////////////////
201+
if (data.toggle) {
202+
$("#component-preview").hide();
203+
var toggleQuestionSelect = document.getElementById(
204+
selectorId + "-toggleQuestion"
205+
);
206+
for (i = 0; i < toggleQuestionSelect.options.length; i++) {
207+
if (
208+
toggleQuestionSelect.options[i].value == toggleFirstID
209+
) {
210+
toggleQuestionSelect.value = toggleFirstID;
211+
$("#" + selectorId).data(
212+
"toggle_current",
213+
toggleFirstID
214+
);
215+
break;
216+
}
217+
}
218+
toggleQuestionSelect.addEventListener(
219+
"change",
220+
async function () {
221+
await this.togglePreview(
222+
toggleQuestionSelect.parentElement.id
223+
);
224+
}.bind(this)
225+
);
226+
}
227+
///////////////////////////
124228
}
125229
return response;
126230
}
231+
232+
async getToggleSrc(toggleQuestionID) {
233+
let request = new Request(
234+
"/runestone/admin/htmlsrc?acid=" + toggleQuestionID,
235+
{
236+
method: "GET",
237+
}
238+
);
239+
let response = await fetch(request);
240+
let htmlsrc = await response.json();
241+
return htmlsrc;
242+
}
243+
244+
async togglePreview(parentID) {
245+
var parentDiv = document.getElementById(parentID);
246+
var toggleQuestionSelect = parentDiv.getElementsByTagName("select")[0];
247+
var selectedQuestion =
248+
toggleQuestionSelect.options[toggleQuestionSelect.selectedIndex]
249+
.value;
250+
var htmlsrc = await this.getToggleSrc(selectedQuestion);
251+
let res = renderRunestoneComponent(htmlsrc, "component-preview", {
252+
selector_id: "component-preview",
253+
useRunestoneServices: true,
254+
});
255+
// let pd = document.getElementById(preview_div);
256+
// pd.appendChild(renderGradingComponents(sid, selectedQuestion));
257+
258+
let closeButton = document.createElement("button");
259+
$(closeButton).text("Close Preview");
260+
$(closeButton).addClass("btn btn-default");
261+
$(closeButton).click(function (event) {
262+
$("#component-preview").html("");
263+
toggleQuestionSelect.value = $("#" + parentID).data(
264+
"toggle_current"
265+
);
266+
$("#component-preview").hide();
267+
});
268+
$("#component-preview").append(closeButton);
269+
270+
let setButton = document.createElement("button");
271+
$(setButton).text("Select this Problem");
272+
$(setButton).addClass("btn btn-primary");
273+
$(setButton).click(
274+
async function () {
275+
await this.toggleSet(parentID, selectedQuestion, htmlsrc);
276+
$("#component-preview").hide();
277+
}.bind(this)
278+
);
279+
$("#component-preview").append(setButton);
280+
$("#component-preview").show();
281+
}
282+
283+
async toggleSet(parentID, selectedQuestion, htmlsrc) {
284+
var selectorId = parentID + "-toggleSelectedQuestion";
285+
document.getElementById(selectorId).innerHTML = ""; // need to check whether this is even necessary
286+
let res = renderRunestoneComponent(htmlsrc, selectorId, {
287+
selector_id: selectorId,
288+
useRunestoneServices: true,
289+
});
290+
let request = new Request(
291+
"/runestone/ajax/update_selected_question?metaid=" +
292+
parentID +
293+
"&selected=" +
294+
selectedQuestion,
295+
{}
296+
);
297+
let response = await fetch(request);
298+
$("#component-preview").html("");
299+
$("#" + parentID).data("toggle_current", selectedQuestion);
300+
}
127301
}
128302

129303
/*

runestone/selectquestion/selectone.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848

4949
TEMPLATE = """
5050
<div class="runestone alert alert-warning sqcontainer">
51-
<div data-component="selectquestion" id={component_id} {selector} {points} {proficiency} {min_difficulty} {max_difficulty} {autogradable} {not_seen_ever} {primary} {AB}>
51+
<div data-component="selectquestion" id={component_id} {selector} {points} {proficiency} {min_difficulty} {max_difficulty} {autogradable} {not_seen_ever} {primary} {AB} {toggle}>
5252
<p>Loading ...</p>
5353
</div>
5454
</div>
@@ -71,6 +71,7 @@ class SelectQuestion(RunestoneIdDirective):
7171
:min_difficulty: minimum difficulty level
7272
:max_difficulty: maximum difficulty level
7373
:ab: experiment_name
74+
:toggle: allow student to choose which question to answer from the given list, with first question in fromid list being rendered first
7475
7576
Difficulty is measured in one of two ways. For things like multiple choice and
7677
fill in the blank, we can use the % of students that get the answer correct on
@@ -79,7 +80,7 @@ class SelectQuestion(RunestoneIdDirective):
7980
"""
8081

8182
required_arguments = 1
82-
optional_arguments = 0
83+
optional_arguments = 1
8384
has_content = False
8485
option_spec = RunestoneIdDirective.option_spec.copy()
8586
option_spec.update(
@@ -93,6 +94,7 @@ class SelectQuestion(RunestoneIdDirective):
9394
"not_seen_ever": directives.flag,
9495
"primary": directives.flag,
9596
"ab": directives.unchanged,
97+
"toggle": directives.flag,
9698
}
9799
)
98100

@@ -180,6 +182,11 @@ def run(self):
180182
else:
181183
self.options["AB"] = ""
182184

185+
if "toggle" in self.options:
186+
self.options["toggle"] = "data-toggle=true"
187+
else:
188+
self.options["toggle"] = ""
189+
183190
maybeAddToAssignment(self)
184191

185192
res = TEMPLATE.format(**self.options)

0 commit comments

Comments
 (0)