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

Commit ae4db0b

Browse files
committed
Fix: Display code for LP problems when not on the problem's page
(e.g. in an assignment, in the instructor grading interface).
1 parent 0cb1ff6 commit ae4db0b

File tree

1 file changed

+30
-10
lines changed

1 file changed

+30
-10
lines changed

runestone/lp/js/lp.js

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,27 @@ class LP extends RunestoneBase {
5454
.siblings(".lp-feedback")
5555
.children("div");
5656
// Use a nice editor.
57-
let that = this;
5857
this.textAreas = [];
59-
$(".code_snippet").each(function (index, element) {
58+
this.initTextAreas();
59+
// Handle clicks to the "Save and run" button.
60+
let that = this;
61+
$(this.element).click((eventObject) =>
62+
that.onSaveAndRun(eventObject).then(null)
63+
);
64+
this.checkServer("lp_build", true);
65+
}
66+
67+
// Look for each code snippet (a textarea). Make it a nice CodeMirror editor.
68+
initTextAreas(is_read_only = false) {
69+
let that = this;
70+
// Select only textareas that haven't been initialized with CodeMirror (which sets style="display:none" on the textarea).
71+
$('textarea.code_snippet:not([style="display: none;"])').each(function (index, element) {
6072
let editor = CodeMirror.fromTextArea(element, {
6173
lineNumbers: true,
6274
mode: $(that.element).attr("data-lang"),
6375
indentUnit: 4,
6476
matchBrackets: true,
77+
readOnly: is_read_only,
6578
autoMatchParens: true,
6679
extraKeys: { Tab: "indentMore", "Shift-Tab": "indentLess" },
6780
});
@@ -75,11 +88,6 @@ class LP extends RunestoneBase {
7588
// Keep track of it.
7689
that.textAreas.push(editor);
7790
});
78-
// Handle clicks to the "Save and run" button.
79-
$(this.element).click((eventObject) =>
80-
that.onSaveAndRun(eventObject).then(null)
81-
);
82-
this.checkServer("lp_build", true);
8391
}
8492

8593
// Data structures:
@@ -213,17 +221,29 @@ class LP extends RunestoneBase {
213221

214222
// Store an array of strings in ``data.code_snippets`` into each textarea.
215223
dataToTextareas(data) {
216-
// Find all code snippet textareas.
224+
// For places where textareas aren't provided (instructor grading interface, assignment page), create them. However, these aren't runnable, so disable the "Save and run" button. Assume this is the case when there are no textareas. Reasoning: the page containing the problem contains code intended to be intermingled with the student's answer. If that's not present, we can't build.
225+
if (!this.textAreas.length) {
226+
// The unusual case -- a problem not on its original page. Create textareas to display the code, then initialize them. Note that we can't simply create these in the constructor (which would be convenient) since we don't yet know how many code snippets are associated with the problem.
227+
$(this.element).before((data.answer.code_snippets || []).map(() => `<textarea class="code_snippet"></textarea><br />`));
228+
// Put CodeMirror in read-only mode.
229+
this.initTextAreas(true);
230+
// Disable the "Save and run" button.
231+
$(this.element).prop("disabled", true);
232+
// Now that we have textareas, let the usual case code run.
233+
}
234+
235+
// The usual case -- a problem on its original page. Find all code snippet textareas.
217236
$(this.textAreas).each(function (index, value) {
218237
// Silently ignore if ``data.answer.code_snippets`` or ``data.answer.code_snippets[index]`` isn't defined.
219238
value.setValue((data.answer.code_snippets || "")[index] || "");
220239
});
240+
// Corner case TODO: if a problem is edited after students already submit code so that there are now fewer textareas, display these but don't save them when "Save and run" is pressed. This allows students to (hopefully) re-use code from now-discarded textareas.
221241
}
222242

223243
// Restore answers from storage retrieval done in RunestoneBase.
224244
restoreAnswers(data) {
225-
// We store the answer as a JSON-encoded string in the db / local storage. Restore the actual data structure from it.
226-
data.answer = JSON.parse(data.answer);
245+
// We store the answer as a JSON-encoded string in the db / local storage. Restore the actual data structure from it. Avoid exceptions if no data is available.
246+
data.answer = JSON.parse(data.answer || "{}");
227247
this.dataToTextareas(data);
228248
this.displayAnswer(data);
229249
}

0 commit comments

Comments
 (0)