From c25b2f206eefd8e24dd9411ab311622d0923ae92 Mon Sep 17 00:00:00 2001 From: Trevor Gunn Date: Sat, 20 Apr 2024 15:37:24 -0400 Subject: [PATCH 1/2] add custom script question type --- src/QuizQuestions.jl | 2 +- src/html_templates.jl | 9 +++++++++ src/question_types.jl | 43 +++++++++++++++++++++++++++++++++++++++++++ src/show_methods.jl | 19 +++++++++++++++++++ 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/src/QuizQuestions.jl b/src/QuizQuestions.jl index 6f5e322..cecf57d 100644 --- a/src/QuizQuestions.jl +++ b/src/QuizQuestions.jl @@ -13,7 +13,7 @@ include("latex_show_methods.jl") export numericq, buttonq, radioq, booleanq, yesnoq, multiq, multibuttonq, matchq, - stringq, fillblankq, + stringq, scriptq, fillblankq, hotspotq, plotlylightq, scorecard diff --git a/src/html_templates.jl b/src/html_templates.jl index 29af52d..bcf7b5e 100644 --- a/src/html_templates.jl +++ b/src/html_templates.jl @@ -84,6 +84,15 @@ document.getElementById("{{:ID}}").addEventListener("change", function() { }); """ +## +html_templates["function_grading_script"] = jmt""" +document.getElementById("{{:ID}}").addEventListener("change", function() { + var correct = ({{{:FUNCTION}}})(this.value); + var msgBox = document.getElementById('{{:ID}}_message'); + $(grading_partial) +}); +""" + ## html_templates["inputq_form"] = mt"""
diff --git a/src/question_types.jl b/src/question_types.jl index f56c5ea..119f688 100644 --- a/src/question_types.jl +++ b/src/question_types.jl @@ -36,6 +36,49 @@ stringq(re, label="First 3 letters...") stringq(re::Regex; label="", hint="", explanation="", placeholder=nothing) = Stringq(re, label, hint, explanation, placeholder) +## +mutable struct Scriptq <: Question + funct::AbstractString + label + hint + explanation + placeholder +end + +""" + scriptq(funct::AbstractString, runonce::AbstractString=""; label="", hint="", explanation="", placeholder="") + +Check string answer with custom script + +Arguments: + +* `funct`: a string representing the name of a JavaScript function/closure of signature `(str: string): boolean` + +* `label`: optional label for the form element + +* `hint`: optional plain-text hint that can be seen on hover + +* `explanation`: text to display on a wrong selection + +* `placeholder`: text shown when input widget is initially drawn + +## Example + +```javascript +// in JavaScript +function threshold(t) { + return (input) => input >= t; +} +``` + +```julia +# in Julia +stringq("threshold(42)", label="A large number") +``` + +""" +scriptq(funct::AbstractString; label="", hint="", explanation="", placeholder=nothing) = + Scriptq(funct, label, hint, explanation, placeholder) ## mutable struct Numericq <: Question diff --git a/src/show_methods.jl b/src/show_methods.jl index a4068e0..fd50883 100644 --- a/src/show_methods.jl +++ b/src/show_methods.jl @@ -89,6 +89,25 @@ function prepare_question(x::Stringq, ID) end +function prepare_question(x::Scriptq, ID) + + FORM = Mustache.render(html_templates["inputq_form"]; + ID=ID, + PLACEHOLDER = isnothing(x.placeholder) ? "Text answer" : x.placeholder, + TYPE="text", + HINT = length(x.label) == 0 ? x.hint : "" + ) + + GRADING_SCRIPT = + Mustache.render(html_templates["function_grading_script"]; + ID = ID, + FUNCTION = x.funct, + INCORRECT = "Incorrect", + CORRECT = "Correct" + ) + (FORM, GRADING_SCRIPT) + +end function _make_item(i, choice, ID) choice′ = sprint(io -> Markdown.html(io, Markdown.parse(choice))) From aa76b6e8f5889f751c5adac93819126122ca80ea Mon Sep 17 00:00:00 2001 From: Trevor Gunn Date: Sat, 20 Apr 2024 18:22:04 -0400 Subject: [PATCH 2/2] document scriptq --- README.md | 2 +- docs/src/index.md | 10 ++++++++++ examples/documenter.md | 7 +++++++ examples/quarto.qmd | 8 ++++++++ examples/weave.jmd | 5 +++++ 5 files changed, 31 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f1ddb20..d028034 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![](https://img.shields.io/badge/docs-dev-blue.svg)](https://jverzani.github.io/QuizQuestions.jl/dev/) -A simple means to make basic web pages using Markdown with self-grading quiz questions. Question types are for numeric response, text response (graded with a regular expression), matching, a selection of one from many, or one or more from many. Can be used with Weave, Documenter, [quarto](https://quarto.org), or Pluto. +A simple means to make basic web pages using Markdown with self-grading quiz questions. Question types are for numeric response, text response (graded with a regular expression or by JavaScript function), matching, a selection of one from many, or one or more from many. Can be used with Weave, Documenter, [quarto](https://quarto.org), or Pluto. The package creates `show` methods for mime type `text/html` for a few objects that produce HTML showing an input widget with attached javascript code to grade the input once the widget loses focus. diff --git a/docs/src/index.md b/docs/src/index.md index 473f6d7..d918a29 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -189,6 +189,15 @@ fillblankq(question, r"^lazy$") ---- +(like `scriptq`) + +```@example quiz_question +funct = "(input) => input >= 42" +scriptq(funct, label="a large number", explanation="should be at least 6 * 7") +``` + +---- + (like `numericq`) ```@example quiz_question @@ -235,6 +244,7 @@ multibuttonq matchq numericq stringq +scriptq fillblankq hotspotq plotlylightq diff --git a/examples/documenter.md b/examples/documenter.md index 0e6aa03..b52c717 100644 --- a/examples/documenter.md +++ b/examples/documenter.md @@ -12,6 +12,13 @@ re = Regex("abc") # hide stringq(re) # hide ``` +Enter a large number + +```@example quiz +funct = "(input) => input >= 42" +scriptq(funct, explanation="should be at least 6 * 7") +``` + What is ``\sin(\frac{\pi}{2})``? ```@example quiz diff --git a/examples/quarto.qmd b/examples/quarto.qmd index 97ffbf3..d9e5d85 100644 --- a/examples/quarto.qmd +++ b/examples/quarto.qmd @@ -14,6 +14,14 @@ re = Regex("abc") stringq(re) ``` +Enter a large number + +```{julia} +#| echo: false +funct = "(input) => input >= 42" +scriptq(funct, explanation="should be at least 6 * 7") +``` + ```{julia} #| echo: false a = 1 diff --git a/examples/weave.jmd b/examples/weave.jmd index e0035b6..056fb62 100644 --- a/examples/weave.jmd +++ b/examples/weave.jmd @@ -11,7 +11,12 @@ re = Regex("abc") stringq(re) ``` +Enter a large number +```julia; echo=false +funct = "(input) => input >= 42" +scriptq(funct, explanation="should be at least 6 * 7") +``` ```julia; echo=false a = 1