Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Book
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
MUDE
Book
Commits
79938d26
Commit
79938d26
authored
1 year ago
by
sheepmax
Browse files
Options
Downloads
Patches
Plain Diff
Add keep output
parent
13328deb
No related branches found
Branches containing commit
No related tags found
Tags containing commit
3 merge requests
!135
Update 2 files
,
!120
New thebe features
,
!101
Thebe new features: tags, aesthetics, default ipywidgets install
Pipeline
#207913
passed
1 year ago
Stage: test
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
book/cookbook/benchmarks/benchmark_tags.ipynb
+218
-6
218 additions, 6 deletions
book/cookbook/benchmarks/benchmark_tags.ipynb
thebe_lite/_static/sphinx-thebe.js
+17
-9
17 additions, 9 deletions
thebe_lite/_static/sphinx-thebe.js
with
235 additions
and
15 deletions
book/cookbook/benchmarks/benchmark_tags.ipynb
+
218
−
6
View file @
79938d26
...
...
@@ -15,7 +15,8 @@
"metadata": {
"tags": [
"thebe-init",
"disable-download"
"disable-download",
"auto-execute"
]
},
"outputs": [],
...
...
@@ -117,10 +118,221 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
"execution_count": 2,
"metadata": {
"tags": [
"remove-input",
"keep-output"
]
},
"outputs": [
{
"data": {
"text/html": [
"<div id=\"lNqOwViqJIfV\" data-shufflequestions=\"False\"\n",
" data-shuffleanswers=\"True\"\n",
" data-preserveresponses=\"false\"\n",
" data-numquestions=\"1000000\"\n",
" data-maxwidth=\"600\"\n",
" style=\"border-radius: 0px; text-align: left\"> <style>\n",
"#lNqOwViqJIfV {\n",
" --jq-multiple-choice-bg: #6f78ffff;\n",
" --jq-mc-button-bg: #fafafa;\n",
" --jq-mc-button-border: #e0e0e0e0;\n",
" --jq-mc-button-inset-shadow: #555555;\n",
" --jq-many-choice-bg: #f75c03ff;\n",
" --jq-numeric-bg: #392061ff;\n",
" --jq-numeric-input-bg: #c0c0c0;\n",
" --jq-numeric-input-label: #101010;\n",
" --jq-numeric-input-shadow: #999999;\n",
" --jq-incorrect-color: #c80202;\n",
" --jq-correct-color: #009113;\n",
" --jq-text-color: #fafafa;\n",
"}\n",
"\n",
".Quiz {\n",
" max-width: 600px;\n",
" margin-top: 15px;\n",
" margin-left: auto;\n",
" margin-right: auto;\n",
" margin-bottom: 15px;\n",
" padding-bottom: 4px;\n",
" padding-top: 4px;\n",
" line-height: 1.1;\n",
" font-size: 16pt;\n",
" border-radius: inherit;\n",
"}\n",
"\n",
".QuizCode {\n",
" font-size: 14pt;\n",
" margin-top: 10px;\n",
" margin-left: 20px;\n",
" margin-right: 20px;\n",
"}\n",
"\n",
".QuizCode>pre {\n",
" padding: 4px;\n",
"}\n",
"\n",
".Answer {\n",
" margin: 10px 0;\n",
" display: grid;\n",
" grid-template-columns: 1fr 1fr;\n",
" grid-gap: 10px;\n",
" border-radius: inherit;\n",
"}\n",
"\n",
".Feedback {\n",
" font-size: 16pt;\n",
" text-align: center;\n",
" min-height: 2em;\n",
"}\n",
"\n",
".Input {\n",
" align: left;\n",
" font-size: 20pt;\n",
"}\n",
"\n",
".Input-text {\n",
" display: block;\n",
" margin: 10px;\n",
" color: inherit;\n",
" width: 140px;\n",
" background-color: var(--jq-numeric-input-bg);\n",
" color: var(--jq-text-color);\n",
" padding: 5px;\n",
" padding-left: 10px;\n",
" font-family: inherit;\n",
" font-size: 20px;\n",
" font-weight: inherit;\n",
" line-height: 20pt;\n",
" border: none;\n",
" border-radius: 0.2rem;\n",
" transition: box-shadow 0.1s);\n",
"}\n",
"\n",
".Input-text:focus {\n",
" outline: none;\n",
" background-color: var(--jq-numeric-input-bg);\n",
" box-shadow: 0.6rem 0.8rem 1.4rem -0.5rem var(--jq-numeric-input-shadow);\n",
"}\n",
"\n",
".MCButton {\n",
" background: var(--jq-mc-button-bg);\n",
" border: 1px solid var(--jq-mc-button-border);\n",
" border-radius: inherit;\n",
" padding: 10px;\n",
" font-size: 16px;\n",
" cursor: pointer;\n",
" text-align: center;\n",
" display: flex;\n",
" align-items: center;\n",
" justify-content: center;\n",
"}\n",
"\n",
".MCButton p {\n",
" color: inherit;\n",
"}\n",
"\n",
".MultipleChoiceQn {\n",
" padding: 10px;\n",
" background: var(--jq-multiple-choice-bg);\n",
" color: var(--jq-text-color);\n",
" border-radius: inherit;\n",
"}\n",
"\n",
".ManyChoiceQn {\n",
" padding: 10px;\n",
" background: var(--jq-many-choice-bg);\n",
" color: var(--jq-text-color);\n",
" border-radius: inherit;\n",
"}\n",
"\n",
".NumericQn {\n",
" padding: 10px;\n",
" background: var(--jq-numeric-bg);\n",
" color: var(--jq-text-color);\n",
" border-radius: inherit;\n",
"}\n",
"\n",
".NumericQn p {\n",
" color: inherit;\n",
"}\n",
"\n",
".InpLabel {\n",
" line-height: 34px;\n",
" float: left;\n",
" margin-right: 10px;\n",
" color: var(--jq-numeric-input-label);\n",
" font-size: 15pt;\n",
"}\n",
"\n",
".incorrect {\n",
" color: var(--jq-incorrect-color);\n",
"}\n",
"\n",
".correct {\n",
" color: var(--jq-correct-color);\n",
"}\n",
"\n",
".correctButton {\n",
" /*\n",
" background: var(--jq-correct-color);\n",
" */\n",
" animation: correct-anim 0.6s ease;\n",
" animation-fill-mode: forwards;\n",
" color: var(--jq-text-color);\n",
" box-shadow: inset 0px 0px 5px var(--jq-mc-button-inset-shadow);\n",
" outline: none;\n",
"}\n",
"\n",
".incorrectButton {\n",
" animation: incorrect-anim 0.8s ease;\n",
" animation-fill-mode: forwards;\n",
" color: var(--jq-text-color);\n",
" box-shadow: inset 0px 0px 5px var(--jq-mc-button-inset-shadow);\n",
" outline: none;\n",
"}\n",
"\n",
"@keyframes incorrect-anim {\n",
" 100% {\n",
" background-color: var(--jq-incorrect-color);\n",
" }\n",
"}\n",
"\n",
"@keyframes correct-anim {\n",
" 100% {\n",
" background-color: var(--jq-correct-color);\n",
" }\n",
"}\n",
"</style>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/javascript": "var questionslNqOwViqJIfV=[{\"question\": \"If the probability of failure for an individual bridge is 0.1 per year, compute the probability that you cannot drive from City 1 to City 2:\", \"type\": \"numeric\", \"answers\": [{\"type\": \"range\", \"value\": 0.0109, \"correct\": true, \"feedback\": \"Correct.\"}, {\"type\": \"default\", \"feedback\": \"Try again\"}]}];\n // Make a random ID\nfunction makeid(length) {\n var result = [];\n var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n var charactersLength = characters.length;\n for (var i = 0; i < length; i++) {\n result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));\n }\n return result.join('');\n}\n\n// Choose a random subset of an array. Can also be used to shuffle the array\nfunction getRandomSubarray(arr, size) {\n var shuffled = arr.slice(0), i = arr.length, temp, index;\n while (i--) {\n index = Math.floor((i + 1) * Math.random());\n temp = shuffled[index];\n shuffled[index] = shuffled[i];\n shuffled[i] = temp;\n }\n return shuffled.slice(0, size);\n}\n\nfunction printResponses(responsesContainer) {\n var responses=JSON.parse(responsesContainer.dataset.responses);\n var stringResponses='<B>IMPORTANT!</B>To preserve this answer sequence for submission, when you have finalized your answers: <ol> <li> Copy the text in this cell below \"Answer String\"</li> <li> Double click on the cell directly below the Answer String, labeled \"Replace Me\"</li> <li> Select the whole \"Replace Me\" text</li> <li> Paste in your answer string and press shift-Enter.</li><li>Save the notebook using the save icon or File->Save Notebook menu item</li></ul><br><br><br><b>Answer String:</b><br> ';\n console.log(responses);\n responses.forEach((response, index) => {\n if (response) {\n console.log(index + ': ' + response);\n stringResponses+= index + ': ' + response +\"<BR>\";\n }\n });\n responsesContainer.innerHTML=stringResponses;\n}\nfunction check_mc() {\n var id = this.id.split('-')[0];\n //var response = this.id.split('-')[1];\n //console.log(response);\n //console.log(\"In check_mc(), id=\"+id);\n //console.log(event.srcElement.id) \n //console.log(event.srcElement.dataset.correct) \n //console.log(event.srcElement.dataset.feedback)\n\n var label = event.srcElement;\n //console.log(label, label.nodeName);\n var depth = 0;\n while ((label.nodeName != \"LABEL\") && (depth < 20)) {\n label = label.parentElement;\n console.log(depth, label);\n depth++;\n }\n\n\n\n var answers = label.parentElement.children;\n\n //console.log(answers);\n\n\n // Split behavior based on multiple choice vs many choice:\n var fb = document.getElementById(\"fb\" + id);\n\n\n\n\n if (fb.dataset.numcorrect == 1) {\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n //console.log(responsesContainer);\n var response = label.firstChild.innerText;\n if (label.querySelector(\".QuizCode\")){\n response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n }\n console.log(response);\n //console.log(document.getElementById(\"quizWrap\"+id));\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n console.log(responses);\n responses[qnum]= response;\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End code to preserve responses\n \n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n //console.log(child);\n child.className = \"MCButton\";\n }\n\n\n\n if (label.dataset.correct == \"true\") {\n // console.log(\"Correct action\");\n if (\"feedback\" in label.dataset) {\n fb.textContent = jaxify(label.dataset.feedback);\n } else {\n fb.textContent = \"Correct!\";\n }\n label.classList.add(\"correctButton\");\n\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n\n } else {\n if (\"feedback\" in label.dataset) {\n fb.textContent = jaxify(label.dataset.feedback);\n } else {\n fb.textContent = \"Incorrect -- try again.\";\n }\n //console.log(\"Error action\");\n label.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n }\n else {\n var reset = false;\n var feedback;\n if (label.dataset.correct == \"true\") {\n if (\"feedback\" in label.dataset) {\n feedback = jaxify(label.dataset.feedback);\n } else {\n feedback = \"Correct!\";\n }\n if (label.dataset.answered <= 0) {\n if (fb.dataset.answeredcorrect < 0) {\n fb.dataset.answeredcorrect = 1;\n reset = true;\n } else {\n fb.dataset.answeredcorrect++;\n }\n if (reset) {\n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n child.className = \"MCButton\";\n child.dataset.answered = 0;\n }\n }\n label.classList.add(\"correctButton\");\n label.dataset.answered = 1;\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n\n }\n } else {\n if (\"feedback\" in label.dataset) {\n feedback = jaxify(label.dataset.feedback);\n } else {\n feedback = \"Incorrect -- try again.\";\n }\n if (fb.dataset.answeredcorrect > 0) {\n fb.dataset.answeredcorrect = -1;\n reset = true;\n } else {\n fb.dataset.answeredcorrect--;\n }\n\n if (reset) {\n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n child.className = \"MCButton\";\n child.dataset.answered = 0;\n }\n }\n label.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n //console.log(responsesContainer);\n var response = label.firstChild.innerText;\n if (label.querySelector(\".QuizCode\")){\n response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n }\n console.log(response);\n //console.log(document.getElementById(\"quizWrap\"+id));\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n if (label.dataset.correct == \"true\") {\n if (typeof(responses[qnum]) == \"object\"){\n if (!responses[qnum].includes(response))\n responses[qnum].push(response);\n } else{\n responses[qnum]= [ response ];\n }\n } else {\n responses[qnum]= response;\n }\n console.log(responses);\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End save responses stuff\n\n\n\n var numcorrect = fb.dataset.numcorrect;\n var answeredcorrect = fb.dataset.answeredcorrect;\n if (answeredcorrect >= 0) {\n fb.textContent = feedback + \" [\" + answeredcorrect + \"/\" + numcorrect + \"]\";\n } else {\n fb.textContent = feedback + \" [\" + 0 + \"/\" + numcorrect + \"]\";\n }\n\n\n }\n\n if (typeof MathJax != 'undefined') {\n var version = MathJax.version;\n console.log('MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([fb]);\n }\n } else {\n console.log('MathJax not detected');\n }\n\n}\n\nfunction make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id) {\n var shuffled;\n if (shuffle_answers == \"True\") {\n //console.log(shuffle_answers+\" read as true\");\n shuffled = getRandomSubarray(qa.answers, qa.answers.length);\n } else {\n //console.log(shuffle_answers+\" read as false\");\n shuffled = qa.answers;\n }\n\n\n var num_correct = 0;\n\n\n\n shuffled.forEach((item, index, ans_array) => {\n //console.log(answer);\n\n // Make input element\n var inp = document.createElement(\"input\");\n inp.type = \"radio\";\n inp.id = \"quizo\" + id + index;\n inp.style = \"display:none;\";\n aDiv.append(inp);\n\n //Make label for input element\n var lab = document.createElement(\"label\");\n lab.className = \"MCButton\";\n lab.id = id + '-' + index;\n lab.onclick = check_mc;\n var aSpan = document.createElement('span');\n aSpan.classsName = \"\";\n //qDiv.id=\"quizQn\"+id+index;\n if (\"answer\" in item) {\n aSpan.innerHTML = jaxify(item.answer);\n //aSpan.innerHTML=item.answer;\n }\n lab.append(aSpan);\n\n // Create div for code inside question\n var codeSpan;\n if (\"code\" in item) {\n codeSpan = document.createElement('span');\n codeSpan.id = \"code\" + id + index;\n codeSpan.className = \"QuizCode\";\n var codePre = document.createElement('pre');\n codeSpan.append(codePre);\n var codeCode = document.createElement('code');\n codePre.append(codeCode);\n codeCode.innerHTML = item.code;\n lab.append(codeSpan);\n //console.log(codeSpan);\n }\n\n //lab.textContent=item.answer;\n\n // Set the data attributes for the answer\n lab.setAttribute('data-correct', item.correct);\n if (item.correct) {\n num_correct++;\n }\n if (\"feedback\" in item) {\n lab.setAttribute('data-feedback', item.feedback);\n }\n lab.setAttribute('data-answered', 0);\n\n aDiv.append(lab);\n\n });\n\n if (num_correct > 1) {\n outerqDiv.className = \"ManyChoiceQn\";\n } else {\n outerqDiv.className = \"MultipleChoiceQn\";\n }\n\n return num_correct;\n\n}\nfunction check_numeric(ths, event) {\n\n if (event.keyCode === 13) {\n ths.blur();\n\n var id = ths.id.split('-')[0];\n\n var submission = ths.value;\n if (submission.indexOf('/') != -1) {\n var sub_parts = submission.split('/');\n //console.log(sub_parts);\n submission = sub_parts[0] / sub_parts[1];\n }\n //console.log(\"Reader entered\", submission);\n\n if (\"precision\" in ths.dataset) {\n var precision = ths.dataset.precision;\n // console.log(\"1:\", submission)\n submission = Math.round((1 * submission + Number.EPSILON) * 10 ** precision) / 10 ** precision;\n // console.log(\"Rounded to \", submission, \" precision=\", precision );\n }\n\n\n //console.log(\"In check_numeric(), id=\"+id);\n //console.log(event.srcElement.id) \n //console.log(event.srcElement.dataset.feedback)\n\n var fb = document.getElementById(\"fb\" + id);\n fb.style.display = \"none\";\n fb.textContent = \"Incorrect -- try again.\";\n\n var answers = JSON.parse(ths.dataset.answers);\n //console.log(answers);\n\n var defaultFB = \"\";\n var correct;\n var done = false;\n answers.every(answer => {\n //console.log(answer.type);\n\n correct = false;\n // if (answer.type==\"value\"){\n if ('value' in answer) {\n if (submission == answer.value) {\n if (\"feedback\" in answer) {\n fb.textContent = jaxify(answer.feedback);\n } else {\n fb.textContent = jaxify(\"Correct\");\n }\n correct = answer.correct;\n //console.log(answer.correct);\n done = true;\n }\n // } else if (answer.type==\"range\") {\n } else if ('range' in answer) {\n //console.log(answer.range);\n if ((submission >= answer.range[0]) && (submission < answer.range[1])) {\n fb.textContent = jaxify(answer.feedback);\n correct = answer.correct;\n //console.log(answer.correct);\n done = true;\n }\n } else if (answer.type == \"default\") {\n defaultFB = answer.feedback;\n }\n if (done) {\n return false; // Break out of loop if this has been marked correct\n } else {\n return true; // Keep looking for case that includes this as a correct answer\n }\n });\n\n if ((!done) && (defaultFB != \"\")) {\n fb.innerHTML = jaxify(defaultFB);\n //console.log(\"Default feedback\", defaultFB);\n }\n\n fb.style.display = \"block\";\n if (correct) {\n ths.className = \"Input-text\";\n ths.classList.add(\"correctButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n } else {\n ths.className = \"Input-text\";\n ths.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n console.log(submission);\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n //console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n console.log(responses);\n if (submission == ths.value){\n responses[qnum]= submission;\n } else {\n responses[qnum]= ths.value + \"(\" + submission +\")\";\n }\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End code to preserve responses\n\n if (typeof MathJax != 'undefined') {\n var version = MathJax.version;\n console.log('MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([fb]);\n }\n } else {\n console.log('MathJax not detected');\n }\n return false;\n }\n\n}\n\nfunction isValid(el, charC) {\n //console.log(\"Input char: \", charC);\n if (charC == 46) {\n if (el.value.indexOf('.') === -1) {\n return true;\n } else if (el.value.indexOf('/') != -1) {\n var parts = el.value.split('/');\n if (parts[1].indexOf('.') === -1) {\n return true;\n }\n }\n else {\n return false;\n }\n } else if (charC == 47) {\n if (el.value.indexOf('/') === -1) {\n if ((el.value != \"\") && (el.value != \".\")) {\n return true;\n } else {\n return false;\n }\n } else {\n return false;\n }\n } else if (charC == 45) {\n var edex = el.value.indexOf('e');\n if (edex == -1) {\n edex = el.value.indexOf('E');\n }\n\n if (el.value == \"\") {\n return true;\n } else if (edex == (el.value.length - 1)) { // If just after e or E\n return true;\n } else {\n return false;\n }\n } else if (charC == 101) { // \"e\"\n if ((el.value.indexOf('e') === -1) && (el.value.indexOf('E') === -1) && (el.value.indexOf('/') == -1)) {\n // Prev symbol must be digit or decimal point:\n if (el.value.slice(-1).search(/\\d/) >= 0) {\n return true;\n } else if (el.value.slice(-1).search(/\\./) >= 0) {\n return true;\n } else {\n return false;\n }\n } else {\n return false;\n }\n } else {\n if (charC > 31 && (charC < 48 || charC > 57))\n return false;\n }\n return true;\n}\n\nfunction numeric_keypress(evnt) {\n var charC = (evnt.which) ? evnt.which : evnt.keyCode;\n\n if (charC == 13) {\n check_numeric(this, evnt);\n } else {\n return isValid(this, charC);\n }\n}\n\n\n\n\n\nfunction make_numeric(qa, outerqDiv, qDiv, aDiv, id) {\n\n\n\n //console.log(answer);\n\n\n outerqDiv.className = \"NumericQn\";\n aDiv.style.display = 'block';\n\n var lab = document.createElement(\"label\");\n lab.className = \"InpLabel\";\n lab.textContent = \"Type numeric answer here:\";\n aDiv.append(lab);\n\n var inp = document.createElement(\"input\");\n inp.type = \"text\";\n //inp.id=\"input-\"+id;\n inp.id = id + \"-0\";\n inp.className = \"Input-text\";\n inp.setAttribute('data-answers', JSON.stringify(qa.answers));\n if (\"precision\" in qa) {\n inp.setAttribute('data-precision', qa.precision);\n }\n aDiv.append(inp);\n //console.log(inp);\n\n //inp.addEventListener(\"keypress\", check_numeric);\n //inp.addEventListener(\"keypress\", numeric_keypress);\n /*\n inp.addEventListener(\"keypress\", function(event) {\n return numeric_keypress(this, event);\n }\n );\n */\n //inp.onkeypress=\"return numeric_keypress(this, event)\";\n inp.onkeypress = numeric_keypress;\n inp.onpaste = event => false;\n\n inp.addEventListener(\"focus\", function (event) {\n this.value = \"\";\n return false;\n }\n );\n\n\n}\nfunction jaxify(string) {\n var mystring = string;\n\n var count = 0;\n var loc = mystring.search(/([^\\\\]|^)(\\$)/);\n\n var count2 = 0;\n var loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n\n //console.log(loc);\n\n while ((loc >= 0) || (loc2 >= 0)) {\n\n /* Have to replace all the double $$ first with current implementation */\n if (loc2 >= 0) {\n if (count2 % 2 == 0) {\n mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\[\");\n } else {\n mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\]\");\n }\n count2++;\n } else {\n if (count % 2 == 0) {\n mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\(\");\n } else {\n mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\)\");\n }\n count++;\n }\n loc = mystring.search(/([^\\\\]|^)(\\$)/);\n loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n //console.log(mystring,\", loc:\",loc,\", loc2:\",loc2);\n }\n\n //console.log(mystring);\n return mystring;\n}\n\n\nfunction show_questions(json, mydiv) {\n console.log('show_questions');\n //var mydiv=document.getElementById(myid);\n var shuffle_questions = mydiv.dataset.shufflequestions;\n var num_questions = mydiv.dataset.numquestions;\n var shuffle_answers = mydiv.dataset.shuffleanswers;\n var max_width = mydiv.dataset.maxwidth;\n\n if (num_questions > json.length) {\n num_questions = json.length;\n }\n\n var questions;\n if ((num_questions < json.length) || (shuffle_questions == \"True\")) {\n //console.log(num_questions+\",\"+json.length);\n questions = getRandomSubarray(json, num_questions);\n } else {\n questions = json;\n }\n\n //console.log(\"SQ: \"+shuffle_questions+\", NQ: \" + num_questions + \", SA: \", shuffle_answers);\n\n // Iterate over questions\n questions.forEach((qa, index, array) => {\n //console.log(qa.question); \n\n var id = makeid(8);\n //console.log(id);\n\n\n // Create Div to contain question and answers\n var iDiv = document.createElement('div');\n //iDiv.id = 'quizWrap' + id + index;\n iDiv.id = 'quizWrap' + id;\n iDiv.className = 'Quiz';\n iDiv.setAttribute('data-qnum', index);\n iDiv.style.maxWidth =max_width+\"px\";\n mydiv.appendChild(iDiv);\n // iDiv.innerHTML=qa.question;\n \n var outerqDiv = document.createElement('div');\n outerqDiv.id = \"OuterquizQn\" + id + index;\n // Create div to contain question part\n var qDiv = document.createElement('div');\n qDiv.id = \"quizQn\" + id + index;\n \n if (qa.question) {\n iDiv.append(outerqDiv);\n\n //qDiv.textContent=qa.question;\n qDiv.innerHTML = jaxify(qa.question);\n outerqDiv.append(qDiv);\n }\n\n // Create div for code inside question\n var codeDiv;\n if (\"code\" in qa) {\n codeDiv = document.createElement('div');\n codeDiv.id = \"code\" + id + index;\n codeDiv.className = \"QuizCode\";\n var codePre = document.createElement('pre');\n codeDiv.append(codePre);\n var codeCode = document.createElement('code');\n codePre.append(codeCode);\n codeCode.innerHTML = qa.code;\n outerqDiv.append(codeDiv);\n //console.log(codeDiv);\n }\n\n\n // Create div to contain answer part\n var aDiv = document.createElement('div');\n aDiv.id = \"quizAns\" + id + index;\n aDiv.className = 'Answer';\n iDiv.append(aDiv);\n\n //console.log(qa.type);\n\n var num_correct;\n if ((qa.type == \"multiple_choice\") || (qa.type == \"many_choice\") ) {\n num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n if (\"answer_cols\" in qa) {\n //aDiv.style.gridTemplateColumns = 'auto '.repeat(qa.answer_cols);\n aDiv.style.gridTemplateColumns = 'repeat(' + qa.answer_cols + ', 1fr)';\n }\n } else if (qa.type == \"numeric\") {\n //console.log(\"numeric\");\n make_numeric(qa, outerqDiv, qDiv, aDiv, id);\n }\n\n\n //Make div for feedback\n var fb = document.createElement(\"div\");\n fb.id = \"fb\" + id;\n //fb.style=\"font-size: 20px;text-align:center;\";\n fb.className = \"Feedback\";\n fb.setAttribute(\"data-answeredcorrect\", 0);\n fb.setAttribute(\"data-numcorrect\", num_correct);\n iDiv.append(fb);\n\n\n });\n var preserveResponses = mydiv.dataset.preserveresponses;\n console.log(preserveResponses);\n console.log(preserveResponses == \"true\");\n if (preserveResponses == \"true\") {\n console.log(preserveResponses);\n // Create Div to contain record of answers\n var iDiv = document.createElement('div');\n iDiv.id = 'responses' + mydiv.id;\n iDiv.className = 'JCResponses';\n // Create a place to store responses as an empty array\n iDiv.setAttribute('data-responses', '[]');\n\n // Dummy Text\n iDiv.innerHTML=\"<b>Select your answers and then follow the directions that will appear here.</b>\"\n //iDiv.className = 'Quiz';\n mydiv.appendChild(iDiv);\n }\n//console.log(\"At end of show_questions\");\n if (typeof MathJax != 'undefined') {\n console.log(\"MathJax version\", MathJax.version);\n var version = MathJax.version;\n setTimeout(function(){\n var version = MathJax.version;\n console.log('After sleep, MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([mydiv]);\n }\n }, 500);\nif (typeof version == 'undefined') {\n } else\n {\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([mydiv]);\n } else {\n console.log(\"MathJax not found\");\n }\n }\n }\n return false;\n}\n/* This is to handle asynchrony issues in loading Jupyter notebooks\n where the quiz has been previously run. The Javascript was generally\n being run before the div was added to the DOM. I tried to do this\n more elegantly using Mutation Observer, but I didn't get it to work.\n\n Someone more knowledgeable could make this better ;-) */\n\n function try_show() {\n if(document.getElementById(\"lNqOwViqJIfV\")) {\n show_questions(questionslNqOwViqJIfV, lNqOwViqJIfV); \n } else {\n setTimeout(try_show, 200);\n }\n };\n \n {\n // console.log(element);\n\n //console.log(\"lNqOwViqJIfV\");\n // console.log(document.getElementById(\"lNqOwViqJIfV\"));\n\n try_show();\n }\n ",
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import json\n",
"from jupyterquiz import display_quiz\n",
"with open(\"../jupyterquizexample.json\", \"r\") as file:\n",
" questions=json.load(file)\n",
"\n",
"display_quiz(questions, border_radius=0)"
]
}
],
"metadata": {
...
...
@@ -140,7 +352,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.1
0.6
"
"version": "3.1
1.2
"
},
"vscode": {
"interpreter": {
...
...
%% Cell type:markdown id: tags:
# Benchmarks: cell tags
This page includes benchmarks for the behaviour of different cell tags with Thebe.
%% Cell type:code id: tags:thebe-init,disable-download
%% Cell type:code id: tags:thebe-init,disable-download
,auto-execute
```
python
# Thebe init
print
(
"
This should show on startup
"
)
```
%% Cell type:code id: tags:hide-input
```
python
# Hide input
print
(
"
You shouldn
'
t be able to see this without expanding the dropdown.
"
)
print
(
"
But the output should be shown outside of it!
"
)
```
%% Cell type:code id: tags:thebe-remove-input-init
```
python
# Remove input
print
(
"
This should be shown despite the lack of input.
"
)
```
%% Cell type:code id: tags:thebe-remove-input-init
```
python
# Remove input should preserve placeholder output
print
(
"
This output should still be shown until execution.
"
)
```
%% Output
This output should still be shown until execution.
%% Cell type:code id: tags:
```
python
# Predefined output should be removed upon execution
print
(
"
Already ran this locally
"
)
```
%% Output
Already ran this locally
%% Cell type:code id: tags:hide-input
```
python
# Hide input with predefined output should show predefined output until execution
print
(
"
I
'
m free from the dropdown!
"
)
```
%% Output
I'm free from the dropdown!
%% Cell type:code id: tags:
%% Cell type:code id: tags:
remove-input,keep-output
```
python
import
json
from
jupyterquiz
import
display_quiz
with
open
(
"
../jupyterquizexample.json
"
,
"
r
"
)
as
file
:
questions
=
json
.
load
(
file
)
display_quiz
(
questions
,
border_radius
=
0
)
```
%% Output
...
...
This diff is collapsed.
Click to expand it.
thebe_lite/_static/sphinx-thebe.js
+
17
−
9
View file @
79938d26
...
...
@@ -195,10 +195,14 @@ var modifyDOMForThebe = () => {
// We remove all pre-existing cell output because they play poorly with Thebe
// This also means we need special tracking for cells with removed input because no HTML is generated for their input
// Hopefully we can achieve this with minimal changes and a special new tag
const
outputDivs
=
document
.
querySelectorAll
(
"
.cell_output
"
);
outputDivs
.
forEach
((
div
,
_
)
=>
div
.
remove
());
// Find all code cells, replace with Thebe interactive code cells
const
cellOutputs
=
document
.
querySelectorAll
(
"
.cell_output
"
);
cellOutputs
.
forEach
((
output
,
index
)
=>
{
if
(
output
&&
!
output
.
classList
.
contains
(
"
keep
"
))
{
output
.
remove
();
}
});
const
codeCells
=
document
.
querySelectorAll
(
thebe_selector
);
codeCells
.
forEach
((
codeCell
,
index
)
=>
{
const
codeCellId
=
(
index
)
=>
`codecell
${
index
}
`
;
...
...
@@ -213,12 +217,6 @@ var modifyDOMForThebe = () => {
if
(
codeCellText
)
{
codeCellText
.
setAttribute
(
"
data-language
"
,
dataLanguage
);
codeCellText
.
setAttribute
(
"
data-executable
"
,
"
true
"
);
// If we had an output, insert it just after the `pre` cell
if
(
codeCellOutput
)
{
$
(
codeCellOutput
).
attr
(
"
data-output
"
,
""
);
$
(
codeCellOutput
).
insertAfter
(
codeCellText
);
}
}
// Remove sphinx-copybutton blocks, which are common in Sphinx
...
...
@@ -506,6 +504,14 @@ function handleDisableDownloadTag(element) {
$
(
"
.dropdown-download-buttons
"
).
remove
();
}
function
handleAutoExecuteTag
(
element
)
{
$
(
"
.dropdown-launch-buttons button
"
).
click
();
}
function
handleKeepOutputTag
(
element
)
{
element
.
querySelector
(
"
.cell_output
"
).
classList
.
add
(
"
keep
"
);
}
// Deal with custom-defined tags to properly prepare Thebe and DOM
// Current special tags: thebe-remove-input-init
function
consumeSpecialTags
()
{
...
...
@@ -513,6 +519,8 @@ function consumeSpecialTags() {
{
tag
:
"
thebe-remove-input-init
"
,
handler
:
handleThebeRemoveInputTag
},
{
tag
:
"
disable-execution
"
,
handler
:
handleDisableExecutionTag
},
{
tag
:
"
disable-download
"
,
handler
:
handleDisableDownloadTag
},
{
tag
:
"
auto-execute
"
,
handler
:
handleAutoExecuteTag
},
{
tag
:
"
keep-output
"
,
handler
:
handleKeepOutputTag
},
];
window
.
specialTaggedElements
=
[];
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment