{"version":3,"file":"106.7ac0084ce72ad871.bundle.js","mappings":"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","sources":["webpack://WebComponents/./runestone/fitb/js/fitb-i18n.en.js","webpack://WebComponents/./runestone/fitb/js/fitb-i18n.pt-br.js","webpack://WebComponents/./runestone/fitb/js/fitb.js","webpack://WebComponents/./runestone/fitb/js/timedfitb.js"],"sourcesContent":["$.i18n().load({\n en: {\n msg_no_answer: \"No answer provided.\",\n msg_fitb_check_me: \"Check me\",\n msg_fitb_compare_me: \"Compare me\",\n },\n});\n","$.i18n().load({\n \"pt-br\": {\n msg_no_answer: \"Nenhuma resposta dada.\",\n msg_fitb_check_me: \"Verificar\",\n msg_fitb_compare_me: \"Comparar\"\n },\n});\n","// *********\n// |docname|\n// *********\n// This file contains the JS for the Runestone fillintheblank component. It was created By Isaiah Mayerchak and Kirby Olson, 6/4/15 then revised by Brad Miller, 2/7/20.\n\"use strict\";\n\nimport RunestoneBase from \"../../common/js/runestonebase.js\";\nimport \"./fitb-i18n.en.js\";\nimport \"./fitb-i18n.pt-br.js\";\nimport \"../css/fitb.css\";\n\nexport var FITBList = {}; // Object containing all instances of FITB that aren't a child of a timed assessment.\n\n// FITB constructor\nexport default class FITB extends RunestoneBase {\n constructor(opts) {\n super(opts);\n var orig = opts.orig; // entire

element\n this.useRunestoneServices = opts.useRunestoneServices;\n this.origElem = orig;\n this.divid = orig.id;\n this.correct = null;\n // See comments in fitb.py for the format of ``feedbackArray`` (which is identical in both files).\n //\n // Find the script tag containing JSON and parse it. See `SO `_. If this parses to ``false``, then no feedback is available; server-side grading will be performed.\n this.feedbackArray = JSON.parse(\n this.scriptSelector(this.origElem).html()\n );\n this.createFITBElement();\n this.caption = \"Fill in the Blank\";\n this.addCaption(\"runestone\");\n this.checkServer(\"fillb\", true);\n if (typeof Prism !== \"undefined\") {\n Prism.highlightAllUnder(this.containerDiv);\n }\n }\n // Find the script tag containing JSON in a given root DOM node.\n scriptSelector(root_node) {\n return $(root_node).find(`script[type=\"application/json\"]`);\n }\n /*===========================================\n ==== Functions generating final HTML ====\n ===========================================*/\n createFITBElement() {\n this.renderFITBInput();\n this.renderFITBButtons();\n this.renderFITBFeedbackDiv();\n // replaces the intermediate HTML for this component with the rendered HTML of this component\n $(this.origElem).replaceWith(this.containerDiv);\n }\n renderFITBInput() {\n // The text [input] elements are created by the template.\n this.containerDiv = document.createElement(\"div\");\n this.containerDiv.id = this.divid;\n // Copy the original elements to the container holding what the user will see.\n $(this.origElem).children().clone().appendTo(this.containerDiv);\n // Remove the script tag.\n this.scriptSelector(this.containerDiv).remove();\n // Set the class for the text inputs, then store references to them.\n let ba = $(this.containerDiv).find(\":input\");\n ba.attr(\"class\", \"form form-control selectwidthauto\");\n ba.attr(\"aria-label\", \"input area\");\n this.blankArray = ba.toArray();\n // When a blank is changed mark this component as interacted with.\n // And set a class on the component in case we want to render components that have been used\n // differently\n for (let blank of this.blankArray) {\n $(blank).change(this.recordAnswered.bind(this));\n }\n }\n\n recordAnswered() {\n this.isAnswered = true;\n //let rcontainer = this.containerDiv.closest(\".runestone\");\n //rcontainer.addClass(\"answered\");\n }\n\n renderFITBButtons() {\n // \"submit\" button and \"compare me\" button\n this.submitButton = document.createElement(\"button\");\n this.submitButton.textContent = $.i18n(\"msg_fitb_check_me\");\n $(this.submitButton).attr({\n class: \"btn btn-success\",\n name: \"do answer\",\n type: \"button\",\n });\n this.submitButton.addEventListener(\n \"click\",\n function () {\n this.checkCurrentAnswer();\n this.logCurrentAnswer();\n }.bind(this),\n false\n );\n this.containerDiv.appendChild(document.createElement(\"br\"));\n this.containerDiv.appendChild(document.createElement(\"br\"));\n this.containerDiv.appendChild(this.submitButton);\n if (this.useRunestoneServices) {\n this.compareButton = document.createElement(\"button\");\n $(this.compareButton).attr({\n class: \"btn btn-default\",\n id: this.origElem.id + \"_bcomp\",\n disabled: \"\",\n name: \"compare\",\n });\n this.compareButton.textContent = $.i18n(\"msg_fitb_compare_me\");\n this.compareButton.addEventListener(\n \"click\",\n function () {\n this.compareFITBAnswers();\n }.bind(this),\n false\n );\n this.containerDiv.appendChild(this.compareButton);\n }\n this.containerDiv.appendChild(document.createElement(\"div\"));\n }\n renderFITBFeedbackDiv() {\n this.feedBackDiv = document.createElement(\"div\");\n this.feedBackDiv.id = this.divid + \"_feedback\";\n this.containerDiv.appendChild(document.createElement(\"br\"));\n this.containerDiv.appendChild(this.feedBackDiv);\n }\n /*===================================\n === Checking/loading from storage ===\n ===================================*/\n restoreAnswers(data) {\n var arr;\n // Restore answers from storage retrieval done in RunestoneBase.\n try {\n // The newer format encodes data as a JSON object.\n arr = JSON.parse(data.answer);\n // The result should be an array. If not, try comma parsing instead.\n if (!Array.isArray(arr)) {\n throw new Error();\n }\n } catch (err) {\n // The old format didn't.\n arr = data.answer.split(\",\");\n }\n for (var i = 0; i < this.blankArray.length; i++) {\n $(this.blankArray[i]).attr(\"value\", arr[i]);\n }\n // Use the feedback from the server, or recompute it locally.\n if (!this.feedbackArray) {\n this.displayFeed = data.displayFeed;\n this.correct = data.correct;\n this.isCorrectArray = data.isCorrectArray;\n // Only render if all the data is present; local storage might have old data missing some of these items.\n if (\n typeof this.displayFeed !== \"undefined\" &&\n typeof this.correct !== \"undefined\" &&\n typeof this.isCorrectArray !== \"undefined\"\n ) {\n this.renderFeedback();\n }\n } else {\n this.checkCurrentAnswer();\n }\n }\n checkLocalStorage() {\n // Loads previous answers from local storage if they exist\n var storedData;\n if (this.graderactive) {\n return;\n }\n var len = localStorage.length;\n if (len > 0) {\n var ex = localStorage.getItem(this.localStorageKey());\n if (ex !== null) {\n try {\n storedData = JSON.parse(ex);\n var arr = storedData.answer;\n } catch (err) {\n // error while parsing; likely due to bad value stored in storage\n console.log(err.message);\n localStorage.removeItem(this.localStorageKey());\n return;\n }\n this.restoreAnswers(storedData);\n }\n }\n }\n setLocalStorage(data) {\n let key = this.localStorageKey();\n localStorage.setItem(key, JSON.stringify(data));\n }\n\n checkCurrentAnswer() {\n // Start of the evaluation chain\n this.isCorrectArray = [];\n this.displayFeed = [];\n this.given_arr = [];\n for (var i = 0; i < this.blankArray.length; i++)\n this.given_arr.push(this.blankArray[i].value);\n if (this.useRunestoneServices) {\n if (eBookConfig.enableCompareMe) {\n this.enableCompareButton();\n }\n }\n // Grade locally if we can't ask the server to grade.\n if (this.feedbackArray) {\n this.evaluateAnswers();\n if (!this.isTimed) {\n this.renderFeedback();\n }\n }\n }\n\n async logCurrentAnswer(sid) {\n let answer = JSON.stringify(this.given_arr);\n // Save the answer locally.\n let feedback = true;\n this.setLocalStorage({\n answer: answer,\n timestamp: new Date(),\n });\n let data = {\n event: \"fillb\",\n act: answer || \"\",\n answer: answer || \"\",\n correct: this.correct ? \"T\" : \"F\",\n div_id: this.divid,\n };\n if (typeof sid !== \"undefined\") {\n data.sid = sid;\n feedback = false;\n }\n // Per `logBookEvent `, the result is undefined if there's no server. Otherwise, the server provides the endpoint-specific results in ``data.details``; see `make_json_response`.\n data = await this.logBookEvent(data);\n let detail = data && data.detail;\n if (!feedback) return;\n if (!this.feedbackArray) {\n // On success, update the feedback from the server's grade.\n this.setLocalStorage({\n answer: answer,\n timestamp: detail.timestamp,\n });\n this.correct = detail.correct;\n this.displayFeed = detail.displayFeed;\n this.isCorrectArray = detail.isCorrectArray;\n if (!this.isTimed) {\n this.renderFeedback();\n }\n }\n return detail;\n }\n\n /*==============================\n === Evaluation of answer and ===\n === display feedback ===\n ==============================*/\n // Inputs:\n //\n // - Strings entered by the student in ``this.blankArray[i].value``.\n // - Feedback in ``this.feedbackArray``.\n //\n // Outputs:\n //\n // - ``this.displayFeed`` is an array of HTML feedback.\n // - ``this.isCorrectArray`` is an array of true, false, or null (the question wasn't answered).\n // - ``this.correct`` is true, false, or null (the question wasn't answered).\n evaluateAnswers() {\n // Keep track if all answers are correct or not.\n this.correct = true;\n for (var i = 0; i < this.blankArray.length; i++) {\n var given = this.blankArray[i].value;\n // If this blank is empty, provide no feedback for it.\n if (given === \"\") {\n this.isCorrectArray.push(null);\n this.displayFeed.push($.i18n(\"msg_no_answer\"));\n this.correct = false;\n } else {\n // Look through all feedback for this blank. The last element in the array always matches. If no feedback for this blank exists, use an empty list.\n var fbl = this.feedbackArray[i] || [];\n for (var j = 0; j < fbl.length; j++) {\n // The last item of feedback always matches.\n if (j === fbl.length - 1) {\n this.displayFeed.push(fbl[j][\"feedback\"]);\n break;\n }\n // If this is a regexp...\n if (\"regex\" in fbl[j]) {\n var patt = RegExp(\n fbl[j][\"regex\"],\n fbl[j][\"regexFlags\"]\n );\n if (patt.test(given)) {\n this.displayFeed.push(fbl[j][\"feedback\"]);\n break;\n }\n } else {\n // This is a number.\n console.assert(\"number\" in fbl[j]);\n var [min, max] = fbl[j][\"number\"];\n // Convert the given string to a number. While there are `lots of ways `_ to do this; this version supports other bases (hex/binary/octal) as well as floats.\n var actual = +given;\n if (actual >= min && actual <= max) {\n this.displayFeed.push(fbl[j][\"feedback\"]);\n break;\n }\n }\n }\n // The answer is correct if it matched the first element in the array. A special case: if only one answer is provided, count it wrong; this is a misformed problem.\n let is_correct = j === 0 && fbl.length > 1;\n this.isCorrectArray.push(is_correct);\n if (!is_correct) {\n this.correct = false;\n }\n }\n }\n this.percent =\n this.isCorrectArray.filter(Boolean).length / this.blankArray.length;\n }\n\n renderFeedback() {\n if (this.correct) {\n $(this.feedBackDiv).attr(\"class\", \"alert alert-info\");\n for (let j = 0; j < this.blankArray.length; j++) {\n $(this.blankArray[j]).removeClass(\"input-validation-error\");\n }\n } else {\n if (this.displayFeed === null) {\n this.displayFeed = \"\";\n }\n for (let j = 0; j < this.blankArray.length; j++) {\n if (this.isCorrectArray[j] !== true) {\n $(this.blankArray[j]).addClass(\"input-validation-error\");\n } else {\n $(this.blankArray[j]).removeClass(\"input-validation-error\");\n }\n }\n $(this.feedBackDiv).attr(\"class\", \"alert alert-danger\");\n }\n var feedback_html = \"

\";\n // Remove the list if it's just one element.\n if (this.displayFeed.length == 1) {\n feedback_html = feedback_html.slice(\n \"\".length\n );\n }\n this.feedBackDiv.innerHTML = feedback_html;\n if (typeof MathJax !== \"undefined\") {\n this.queueMathJax(document.body);\n }\n }\n\n /*==================================\n === Functions for compare button ===\n ==================================*/\n enableCompareButton() {\n this.compareButton.disabled = false;\n }\n // _`compareFITBAnswers`\n compareFITBAnswers() {\n var data = {};\n data.div_id = this.divid;\n data.course = eBookConfig.course;\n jQuery.get(\n `${eBookConfig.new_server_prefix}/assessment/gettop10Answers`,\n data,\n this.compareFITB\n );\n }\n compareFITB(data, status, whatever) {\n var answers = data.detail.res;\n var misc = data.detail.miscdata;\n var body = \"\";\n body += \"\";\n for (var row in answers) {\n body +=\n \"\";\n }\n body += \"
AnswerCount
\" +\n answers[row].answer +\n \"\" +\n answers[row].count +\n \" times
\";\n var html =\n \"\";\n var el = $(html);\n el.modal();\n }\n\n disableInteraction() {\n for (var i = 0; i < this.blankArray.length; i++) {\n this.blankArray[i].disabled = true;\n }\n }\n}\n\n/*=================================\n== Find the custom HTML tags and ==\n== execute our code on them ==\n=================================*/\n$(document).on(\"runestone:login-complete\", function () {\n $(\"[data-component=fillintheblank]\").each(function (index) {\n var opts = {\n orig: this,\n useRunestoneServices: eBookConfig.useRunestoneServices,\n };\n if ($(this).closest(\"[data-component=timedAssessment]\").length == 0) {\n // If this element exists within a timed component, don't render it here\n try {\n FITBList[this.id] = new FITB(opts);\n } catch (err) {\n console.log(\n `Error rendering Fill in the Blank Problem ${this.id}\n Details: ${err}`\n );\n }\n }\n });\n});\n","import FITB from \"./fitb.js\";\nexport default class TimedFITB extends FITB {\n constructor(opts) {\n super(opts);\n this.renderTimedIcon(this.inputDiv);\n this.hideButtons();\n this.needsReinitialization = true;\n }\n hideButtons() {\n $(this.submitButton).hide();\n $(this.compareButton).hide();\n }\n renderTimedIcon(component) {\n // renders the clock icon on timed components. The component parameter\n // is the element that the icon should be appended to.\n var timeIconDiv = document.createElement(\"div\");\n var timeIcon = document.createElement(\"img\");\n $(timeIcon).attr({\n src: \"../_static/clock.png\",\n style: \"width:15px;height:15px\",\n });\n timeIconDiv.className = \"timeTip\";\n timeIconDiv.title = \"\";\n timeIconDiv.appendChild(timeIcon);\n $(component).prepend(timeIconDiv);\n }\n checkCorrectTimed() {\n // Returns if the question was correct, incorrect, or skipped (return null in the last case)\n switch (this.correct) {\n case true:\n return \"T\";\n case false:\n return \"F\";\n default:\n return null;\n }\n }\n hideFeedback() {\n for (var i = 0; i < this.blankArray.length; i++) {\n $(this.blankArray[i]).removeClass(\"input-validation-error\");\n }\n this.feedBackDiv.style.display = \"none\";\n }\n\n reinitializeListeners() {\n for (let blank of this.blankArray) {\n $(blank).change(this.recordAnswered.bind(this));\n }\n }\n}\n\nif (typeof window.component_factory === \"undefined\") {\n window.component_factory = {};\n}\nwindow.component_factory.fillintheblank = function (opts) {\n if (opts.timed) {\n return new TimedFITB(opts);\n }\n return new FITB(opts);\n};\n"],"names":["$","i18n","load","en","msg_no_answer","msg_fitb_check_me","msg_fitb_compare_me","FITBList","FITB","constructor","opts","super","orig","this","useRunestoneServices","origElem","divid","id","correct","feedbackArray","JSON","parse","scriptSelector","html","createFITBElement","caption","addCaption","checkServer","Prism","highlightAllUnder","containerDiv","root_node","find","renderFITBInput","renderFITBButtons","renderFITBFeedbackDiv","replaceWith","document","createElement","children","clone","appendTo","remove","ba","attr","blankArray","toArray","blank","change","recordAnswered","bind","isAnswered","submitButton","textContent","class","name","type","addEventListener","checkCurrentAnswer","logCurrentAnswer","appendChild","compareButton","disabled","compareFITBAnswers","feedBackDiv","restoreAnswers","data","arr","answer","Array","isArray","Error","err","split","i","length","displayFeed","isCorrectArray","renderFeedback","checkLocalStorage","storedData","graderactive","localStorage","ex","getItem","localStorageKey","console","log","message","removeItem","setLocalStorage","key","setItem","stringify","given_arr","push","value","eBookConfig","enableCompareMe","enableCompareButton","evaluateAnswers","isTimed","async","sid","feedback","timestamp","Date","event","act","div_id","logBookEvent","detail","given","fbl","j","RegExp","test","assert","min","max","actual","is_correct","percent","filter","Boolean","removeClass","addClass","feedback_html","slice","innerHTML","MathJax","queueMathJax","body","course","jQuery","get","new_server_prefix","compareFITB","status","whatever","answers","res","miscdata","row","count","modal","disableInteraction","on","each","index","closest","TimedFITB","renderTimedIcon","inputDiv","hideButtons","needsReinitialization","hide","component","timeIconDiv","timeIcon","src","style","className","title","prepend","checkCorrectTimed","hideFeedback","display","reinitializeListeners","window","component_factory","fillintheblank","timed"],"sourceRoot":""}