Skip to content

Instantly share code, notes, and snippets.

@veilkev
Last active October 30, 2024 20:16
Show Gist options
  • Save veilkev/80b337d677a1170d5812c6bf940c5c71 to your computer and use it in GitHub Desktop.
Save veilkev/80b337d677a1170d5812c6bf940c5c71 to your computer and use it in GitHub Desktop.
Anki - Fill-in-the-Blank Template
<!-- Fields (Example): -->
<!-- Question: The #blank is the powerhouse of a #blank #[involves biology] -->
<!-- Answer: Mitochondria, Cell -->
<!-- Explanation: Any extra comments to display alonside the answer (back) -->
<!-- Use #blank for fill-ins, #[] for hints, and #![] to display text as is -->
<!-- Front Template -->
<div class="quiz-wrapper">
<div class="quiz-container">
<span class="badge">Blanks</span>
<!-- Load the question text and data-answers -->
<div class="question-text" id="question-text" data-answers="{{Answer}}">
{{Question}}
</div>
<div class="fill-blank-container">
<button class="submit-btn" onclick="checkAnswers()">Submit</button>
</div>
<!-- Placeholder for hint text extracted from #[] and #![...] -->
<div id="hint-text" class="hint-text"></div>
</div>
</div>
<script>
// Load correct answers from the data attribute and make them case-insensitive
const correctAnswers = document.getElementById("question-text").dataset.answers.split(",").map(answer => answer.trim().toLowerCase());
// Extract hints from #[...] and #![...] and concatenate them
const questionElement = document.getElementById("question-text");
let questionText = questionElement.innerHTML;
// Extract hints for #[...] and prefix with "Hint: "
const prefixedHints = [...questionText.matchAll(/#\[(.*?)\]/g)].map(match => "Hint: " + match[1]);
// Extract exact text for #![...] without prefix
const exactHints = [...questionText.matchAll(/#!\[(.*?)\]/g)].map(match => match[1]);
// Combine both types of hints
const concatenatedHints = [...prefixedHints, ...exactHints].join(" ");
// Display concatenated hints in the hint-text div
document.getElementById("hint-text").innerHTML = concatenatedHints;
// Remove all hints from the question text
questionText = questionText.replace(/#\[(.*?)\]/g, "").replace(/#!\[(.*?)\]/g, "");
// Replace each instance of #blank in the question text with an input field
let blankIndex = 0;
questionText = questionText.replace(/#blank/g, () => {
blankIndex++;
return `<input type="text" id="user-answer-${blankIndex}" class="blank-input" placeholder="Answer ${blankIndex}">`;
});
questionElement.innerHTML = questionText;
function checkAnswers() {
let isCorrect = true;
// Loop through each blank input and compare it to the correctAnswers array
for (let i = 1; i <= blankIndex; i++) {
const userAnswer = document.getElementById(`user-answer-${i}`).value.trim().toLowerCase();
const correctAnswer = correctAnswers[i - 1]; // Already lowercase
if (userAnswer === correctAnswer) {
document.getElementById(`user-answer-${i}`).classList.add("correct");
} else {
document.getElementById(`user-answer-${i}`).classList.add("incorrect");
isCorrect = false;
}
}
// Provide feedback and reveal answers if necessary
setTimeout(function() { pycmd('ans'); }, isCorrect ? 500 : 1000);
}
</script>
<style>
/* General styling */
.quiz-wrapper {
display: flex;
justify-content: center;
padding: 20px;
}
.quiz-container {
width: 100%;
max-width: 600px;
background: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1);
}
/* Badge styling */
.badge {
background-color: #e7f3ff;
color: #1a73e8;
padding: 4px 12px;
border-radius: 12px;
font-size: 14px;
font-weight: 500;
display: inline-block;
margin-bottom: 16px;
}
/* Question text styling */
.question-text {
font-size: 16px;
color: #202124;
margin-bottom: 24px;
line-height: 1.5;
}
/* Fill-in-the-blank input styling */
.blank-input {
padding: 10px;
border: 1px solid #e8eaed;
border-radius: 8px;
font-size: 14px;
color: #202124;
width: auto;
display: inline-block;
min-width: 100px;
}
.blank-input.correct {
background-color: #e6f4ea;
border-color: #137333;
}
.blank-input.incorrect {
background-color: #fce8e6;
border-color: #c5221f;
}
/* Submit button styling */
.submit-btn {
padding: 10px 20px;
background-color: #1a73e8;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
}
.submit-btn:hover {
background-color: #155bb5;
}
/* Hint text styling */
.hint-text {
margin-top: 20px;
font-size: 13px;
color: #888888; /* Gray color for hints */
font-style: italic;
}
</style>
<!-- Back Template -->
<div class="quiz-wrapper">
<div class="quiz-container">
<span class="badge">Answer</span>
<!-- Display the full answer with filled-in answers highlighted in green -->
<div class="question-text" id="filled-answer-text">
<!-- The complete answer with highlighted answers will be inserted here -->
</div>
<!-- Optional Comment Section (from Explanation field if it contains additional text) -->
<div id="comment-text" class="comment-text"></div>
</div>
</div>
<script>
// Get the correct answers from the Answer field and replace #blank in the Question text
const correctAnswersBack = "{{Answer}}".split(",").map(answer => answer.trim());
// Retrieve Explanation as a potential comment
let comment = "{{Explanation}}".trim();
let isCommentOnly = !comment.includes("#blank");
// If Explanation has #blank placeholders, replace them with answers
const completedAnswerText = "{{Question}}".replace(/#blank/g, () => `<span class="answer-highlight">${correctAnswersBack.shift()}</span>`);
document.getElementById("filled-answer-text").innerHTML = completedAnswerText;
// Display Explanation as a comment if it's extra commentary
if (isCommentOnly) {
document.getElementById("comment-text").innerHTML = comment;
}
</script>
/* Styling */
<style>
/* General styling */
.quiz-wrapper {
display: flex;
justify-content: center;
padding: 20px;
}
.quiz-container {
width: 100%;
max-width: 600px;
background: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1);
}
/* Badge styling */
.badge {
background-color: #e7f3ff;
color: #1a73e8;
padding: 4px 12px;
border-radius: 12px;
font-size: 14px;
font-weight: 500;
display: inline-block;
margin-bottom: 16px;
}
/* Question text styling */
.question-text {
font-size: 16px;
color: #202124;
margin-bottom: 24px;
line-height: 1.5;
}
/* Fill-in-the-blank input styling */
.blank-input {
padding: 10px;
border: 1px solid #e8eaed;
border-radius: 8px;
font-size: 14px;
color: #202124;
width: auto;
display: inline-block;
min-width: 100px;
}
.blank-input.correct {
background-color: #e6f4ea;
border-color: #137333;
}
.blank-input.incorrect {
background-color: #fce8e6;
border-color: #c5221f;
}
/* Submit button styling */
.submit-btn {
padding: 10px 20px;
background-color: #1a73e8;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
}
.submit-btn:hover {
background-color: #155bb5;
}
/* Answer container styling */
.answer-container {
margin-top: 20px;
}
.correct-answer {
font-size: 16px;
color: #137333;
font-weight: bold;
}
.explanation-text {
margin-top: 20px;
font-size: 14px;
color: #5f6368;
}
/* Styling for highlighted answer text */
.answer-highlight {
color: #137333; /* Green color for answers */
font-weight: bold;
}
/* Minimal styling for optional comment text */
.comment-text {
margin-top: 12px;
font-size: 13px;
color: #888888; /* Gray color for commentary */
font-style: italic;
}
</style>
@veilkev
Copy link
Author

veilkev commented Oct 30, 2024

Final version

@veilkev
Copy link
Author

veilkev commented Oct 30, 2024

Added hints

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment