diff --git a/bases/rsptx/interactives/runestone/shortanswer/js/shortanswer.js b/bases/rsptx/interactives/runestone/shortanswer/js/shortanswer.js
index 86c74955d..488341997 100644
--- a/bases/rsptx/interactives/runestone/shortanswer/js/shortanswer.js
+++ b/bases/rsptx/interactives/runestone/shortanswer/js/shortanswer.js
@@ -26,18 +26,17 @@ export default class ShortAnswer extends RunestoneBase {
this.question = this.origElem.innerHTML;
this.optional = false;
this.attachURL = opts.attachURL;
- if ($(this.origElem).is("[data-optional]")) {
+ if (this.origElem.hasAttribute("data-optional")) {
this.optional = true;
}
- if ($(this.origElem).is("[data-mathjax]")) {
+ if (this.origElem.hasAttribute("data-mathjax")) {
this.mathjax = true;
}
- this.mathjax = true;
- if ($(this.origElem).is("[data-attachment]")) {
+ if (this.origElem.hasAttribute("data-attachment")) {
this.attachment = true;
}
this.placeholder =
- $(this.origElem).data("placeholder") ||
+ this.origElem.getAttribute("data-placeholder") ||
"Write your answer here";
this.renderHTML();
this.caption = "shortanswer";
@@ -55,7 +54,7 @@ export default class ShortAnswer extends RunestoneBase {
renderHTML() {
this.containerDiv = document.createElement("div");
this.containerDiv.id = this.divid;
- $(this.containerDiv).addClass(this.origElem.getAttribute("class"));
+ this.containerDiv.classList.add(...(this.origElem.getAttribute("class") || "").split(" ").filter(Boolean));
this.newForm = document.createElement("form");
this.newForm.id = this.divid + "_journal";
this.newForm.name = this.newForm.id;
@@ -65,13 +64,13 @@ export default class ShortAnswer extends RunestoneBase {
this.newForm.appendChild(this.fieldSet);
this.firstLegendDiv = document.createElement("div");
this.firstLegendDiv.innerHTML = this.question;
- $(this.firstLegendDiv).addClass("journal-question");
+ this.firstLegendDiv.classList.add("journal-question");
this.fieldSet.appendChild(this.firstLegendDiv);
this.jInputDiv = document.createElement("div");
this.jInputDiv.id = this.divid + "_journal_input";
this.fieldSet.appendChild(this.jInputDiv);
this.jOptionsDiv = document.createElement("div");
- $(this.jOptionsDiv).addClass("journal-options");
+ this.jOptionsDiv.classList.add("journal-options");
this.jInputDiv.appendChild(this.jOptionsDiv);
this.jTextArea = document.createElement("textarea");
let self = this;
@@ -79,10 +78,11 @@ export default class ShortAnswer extends RunestoneBase {
self.isAnswered = true;
};
this.jTextArea.id = this.divid + "_solution";
- $(this.jTextArea).attr("aria-label", "textarea");
+ this.jTextArea.setAttribute("aria-label", "textarea");
this.jTextArea.placeholder = this.placeholder;
- $(this.jTextArea).css("display:inline, width:530px");
- $(this.jTextArea).addClass("form-control");
+ this.jTextArea.style.display = "inline";
+ this.jTextArea.style.width = "530px";
+ this.jTextArea.classList.add("form-control");
this.jTextArea.rows = 4;
this.jTextArea.cols = 50;
this.jOptionsDiv.appendChild(this.jTextArea);
@@ -93,19 +93,14 @@ export default class ShortAnswer extends RunestoneBase {
} else {
this.feedbackDiv.innerHTML = "Your answer has not been saved yet!";
}
- $(this.feedbackDiv).removeClass("alert-success");
- $(this.feedbackDiv).addClass("alert alert-danger");
+ this.feedbackDiv.classList.remove("alert-success");
+ this.feedbackDiv.classList.add("alert", "alert-danger");
}.bind(this);
- this.fieldSet.appendChild(document.createElement("br"));
- if (this.mathjax) {
- this.renderedAnswer = document.createElement("div");
- $(this.renderedAnswer).addClass("latexoutput");
- this.fieldSet.appendChild(this.renderedAnswer);
- }
+
this.buttonDiv = document.createElement("div");
this.fieldSet.appendChild(this.buttonDiv);
this.submitButton = document.createElement("button");
- $(this.submitButton).addClass("btn btn-success");
+ this.submitButton.classList.add("btn", "btn-success");
this.submitButton.type = "button";
this.submitButton.textContent = "Save";
this.submitButton.onclick = function () {
@@ -114,22 +109,35 @@ export default class ShortAnswer extends RunestoneBase {
this.renderFeedback();
}.bind(this);
this.buttonDiv.appendChild(this.submitButton);
+
+ if (this.mathjax) {
+ this.renderedAnswerLabel = document.createElement("label");
+ this.renderedAnswerLabel.innerHTML = "Rendered Answer:";
+ this.renderedAnswerLabel.id = this.divid + "_rendered_answer_label";
+ this.renderedAnswerLabel.style.display = "none";
+ this.fieldSet.appendChild(this.renderedAnswerLabel);
+
+ this.renderedAnswer = document.createElement("div");
+ this.renderedAnswer.classList.add("latexoutput");
+ this.renderedAnswer.setAttribute('aria-labelledby', this.renderedAnswerLabel.id);
+ this.renderedAnswer.setAttribute('aria-live', "polite");
+ this.renderedAnswer.style.display = "none";
+ this.fieldSet.appendChild(this.renderedAnswer);
+ }
this.randomSpan = document.createElement("span");
this.randomSpan.innerHTML = "Instructor's Feedback";
this.fieldSet.appendChild(this.randomSpan);
this.otherOptionsDiv = document.createElement("div");
- $(this.otherOptionsDiv).css("padding-left:20px");
- $(this.otherOptionsDiv).addClass("journal-options");
+ this.otherOptionsDiv.style.paddingLeft = "20px";
+ this.otherOptionsDiv.classList.add("journal-options");
this.fieldSet.appendChild(this.otherOptionsDiv);
// add a feedback div to give user feedback
this.feedbackDiv = document.createElement("div");
- //$(this.feedbackDiv).addClass("bg-info form-control");
- //$(this.feedbackDiv).css("width:530px, background-color:#eee, font-style:italic");
- $(this.feedbackDiv).css("width:530px, font-style:italic");
+ this.feedbackDiv.style.width = "530px";
+ this.feedbackDiv.style.fontStyle = "italic";
this.feedbackDiv.id = this.divid + "_feedback";
this.feedbackDiv.innerHTML = "You have not answered this question yet.";
- $(this.feedbackDiv).addClass("alert alert-danger");
- //this.otherOptionsDiv.appendChild(this.feedbackDiv);
+ this.feedbackDiv.classList.add("alert", "alert-danger");
this.fieldSet.appendChild(this.feedbackDiv);
if (this.attachment) {
let attachDiv = document.createElement("div")
@@ -150,8 +158,7 @@ export default class ShortAnswer extends RunestoneBase {
}
this.containerDiv.appendChild(attachDiv);
}
- //this.fieldSet.appendChild(document.createElement("br"));
- $(this.origElem).replaceWith(this.containerDiv);
+ this.origElem.replaceWith(this.containerDiv);
// This is a stopgap measure for when MathJax is not loaded at all. There is another
// more difficult case that when MathJax is loaded asynchronously we will get here
// before MathJax is loaded. In that case we will need to implement something
@@ -165,14 +172,17 @@ export default class ShortAnswer extends RunestoneBase {
if (this.mathjax) {
value = value.replace(/\$\$(.*?)\$\$/g, "\\[ $1 \\]");
value = value.replace(/\$(.*?)\$/g, "\\( $1 \\)");
- value = value.replace(/\n/g, "
"); // add line breaks
- $(this.renderedAnswer).html(value);
+ value = value.replace(/\n/g, "
");
+ this.renderedAnswer.innerHTML = value;
+
+ this.renderedAnswer.style.display = "block";
+ this.renderedAnswerLabel.style.display = "block";
this.queueMathJax(this.renderedAnswer);
}
}
async checkCurrentAnswer() {
- let value = $(document.getElementById(this.divid + "_solution")).val();
+ let value = document.getElementById(this.divid + "_solution").value;
this.renderMath(value);
this.setLocalStorage({
answer: value,
@@ -181,7 +191,7 @@ export default class ShortAnswer extends RunestoneBase {
}
async logCurrentAnswer(sid) {
- let value = $(document.getElementById(this.divid + "_solution")).val();
+ let value = document.getElementById(this.divid + "_solution").value;
this.renderMath(value);
this.setLocalStorage({
answer: value,
@@ -204,8 +214,8 @@ export default class ShortAnswer extends RunestoneBase {
renderFeedback() {
this.feedbackDiv.innerHTML = "Your answer has been saved.";
- $(this.feedbackDiv).removeClass("alert-danger");
- $(this.feedbackDiv).addClass("alert alert-success");
+ this.feedbackDiv.classList.remove("alert-danger");
+ this.feedbackDiv.classList.add("alert", "alert-success");
}
setLocalStorage(data) {
if (!this.graderactive) {
@@ -233,13 +243,15 @@ export default class ShortAnswer extends RunestoneBase {
localStorage.removeItem(this.localStorageKey());
return;
}
- let solution = $("#" + this.divid + "_solution");
- solution.text(answer);
+ let solution = document.getElementById(this.divid + "_solution");
+ if (solution) {
+ solution.value = answer;
+ }
this.renderMath(answer);
this.feedbackDiv.innerHTML =
"Your current saved answer is shown above.";
- $(this.feedbackDiv).removeClass("alert-danger");
- $(this.feedbackDiv).addClass("alert alert-success");
+ this.feedbackDiv.classList.remove("alert-danger");
+ this.feedbackDiv.classList.add("alert", "alert-success");
}
}
}
@@ -261,16 +273,17 @@ export default class ShortAnswer extends RunestoneBase {
} else {
tsString = "";
}
- $(p).text(tsString);
+ p.textContent = tsString;
if (data.last_answer) {
this.current_answer = "ontime";
let toggle_answer_button = document.createElement("button");
toggle_answer_button.type = "button";
- $(toggle_answer_button).text("Show Late Answer");
- $(toggle_answer_button).addClass("btn btn-warning");
- $(toggle_answer_button).css("margin-left", "5px");
+ toggle_answer_button.textContent = "Show Late Answer";
+ toggle_answer_button.classList.add("btn", "btn-warning");
+ toggle_answer_button.style.marginLeft = "5px";
- $(toggle_answer_button).click(
+ toggle_answer_button.addEventListener(
+ "click",
function () {
var display_timestamp, button_text;
if (this.current_answer === "ontime") {
@@ -289,8 +302,8 @@ export default class ShortAnswer extends RunestoneBase {
this.current_answer = "ontime";
}
this.renderMath(this.answer);
- $(p).text(`Submitted: ${display_timestamp}`);
- $(toggle_answer_button).text(button_text);
+ p.textContent = `Submitted: ${display_timestamp}`;
+ toggle_answer_button.textContent = button_text;
}.bind(this)
);
@@ -305,8 +318,8 @@ export default class ShortAnswer extends RunestoneBase {
}
this.feedbackDiv.innerHTML = feedbackStr;
- $(this.feedbackDiv).removeClass("alert-danger");
- $(this.feedbackDiv).addClass("alert alert-success");
+ this.feedbackDiv.classList.remove("alert-danger");
+ this.feedbackDiv.classList.add("alert", "alert-success");
}
disableInteraction() {
@@ -403,17 +416,17 @@ export default class ShortAnswer extends RunestoneBase {
== Find the custom HTML tags and ==
== execute our code on them ==
=================================*/
-$(document).on("runestone:login-complete", function () {
- $("[data-component=shortanswer]").each(function () {
- if ($(this).closest("[data-component=timedAssessment]").length == 0) {
- // If this element exists within a timed component, don't render it here
+document.addEventListener("runestone:login-complete", function () {
+ document.querySelectorAll("[data-component=shortanswer]").forEach(function (el) {
+ // If this element exists within a timed component, don't render it here
+ if (!el.closest("[data-component=timedAssessment]")) {
try {
- window.componentMap[this.id] = new ShortAnswer({
- orig: this,
+ window.componentMap[el.id] = new ShortAnswer({
+ orig: el,
useRunestoneServices: eBookConfig.useRunestoneServices,
});
} catch (err) {
- console.log(`Error rendering ShortAnswer Problem ${this.id}
+ console.log(`Error rendering ShortAnswer Problem ${el.id}
Details: ${err}`);
}
}
diff --git a/bases/rsptx/interactives/runestone/shortanswer/js/timed_shortanswer.js b/bases/rsptx/interactives/runestone/shortanswer/js/timed_shortanswer.js
index f1d995746..0c5af853a 100644
--- a/bases/rsptx/interactives/runestone/shortanswer/js/timed_shortanswer.js
+++ b/bases/rsptx/interactives/runestone/shortanswer/js/timed_shortanswer.js
@@ -8,27 +8,34 @@ export default class TimedShortAnswer extends ShortAnswer {
this.hideButtons();
}
hideButtons() {
- $(this.submitButton).hide();
+ if (this.submitButton) {
+ this.submitButton.style.display = "none";
+ }
}
renderTimedIcon(component) {
// renders the clock icon on timed components. The component parameter
// is the element that the icon should be appended to.
var timeIconDiv = document.createElement("div");
var timeIcon = document.createElement("img");
- $(timeIcon).attr({
- src: "../_static/clock.png",
- style: "width:15px;height:15px",
- });
+
+ timeIcon.src = "../_static/clock.png";
+ timeIcon.style.width = "15px";
+ timeIcon.style.height = "15px";
+
timeIconDiv.className = "timeTip";
timeIconDiv.title = "";
timeIconDiv.appendChild(timeIcon);
- $(component).prepend(timeIconDiv);
+
+ // If firstChild is null, insertBefore acts like appendChild
+ component.insertBefore(timeIconDiv, component.firstChild);
}
checkCorrectTimed() {
return "I"; // we ignore this in the grading
}
hideFeedback() {
- $(this.feedbackDiv).hide();
+ if (this.feedbackDiv) {
+ this.feedbackDiv.style.display = "none";
+ }
}
}