Add HTMX support for exam overview fragment to enhance user experience

This commit is contained in:
Ross
2025-11-10 21:52:46 +00:00
parent c1eff140f8
commit 52c4f27e2b
2 changed files with 104 additions and 0 deletions
@@ -0,0 +1,68 @@
<div class="exam-overview-fragment">
<h3>Overview: {{ exam }}</h3>
<p>{{ answer_count }} / {{ exam_length }} answered</p>
<div class="overview-list">
<ol class="overview-questions">
{% for q, ans in question_answer_tuples %}
<li class="overview-item" data-qn-index="{{ forloop.counter0 }}">
<div style="display:flex;align-items:center;gap:0.75rem;">
<button class="btn btn-sm btn-outline-secondary goto-from-overview" data-qn="{{ forloop.counter0 }}">{{ forloop.counter }}</button>
<div style="flex:1; padding-left:0.5rem;">{{ q.stem|truncatechars:140|safe }}</div>
<div style="min-width:6rem; text-align:right;">
{% if ans %}
{% if ans.a or ans.b or ans.c or ans.d or ans.e %}
<span class="badge bg-success">Answered</span>
{% else %}
<span class="badge bg-secondary">Unanswered</span>
{% endif %}
{% else %}
<span class="badge bg-secondary">Unanswered</span>
{% endif %}
</div>
</div>
</li>
{% endfor %}
</ol>
</div>
<div style="margin-top:1rem;">
<button id="overview-back-to-question" class="btn btn-primary">Back to current question</button>
</div>
<script>
(function(){
// When a question button is clicked, trigger the hidden goto button in the
// main fragment so the server navigates to that question via the normal flow.
document.querySelectorAll('.goto-from-overview').forEach(function(btn){
btn.addEventListener('click', function(e){
var q = e.currentTarget.dataset.qn;
// Find the form in the currently loaded fragment (it may be the overview itself)
var form = document.querySelector('#question-fragment form.post-form');
if (!form) return;
var goto = form.querySelector('button[name="goto"]') || form.querySelector('#goto-button');
if (!goto) return;
// Set the value and submit
if (goto.tagName.toLowerCase() === 'input' || goto.tagName.toLowerCase() === 'button') {
goto.value = q;
// submit via HTMX by clicking the hidden goto button
goto.click();
}
});
});
// Back button simply reloads the current question fragment by triggering a
// click on the menu item for the current question (if available) or reloads
// via HTMX load of the fragment.
document.getElementById('overview-back-to-question').addEventListener('click', function(){
var menuCurrent = document.querySelector('#menu-list .current-question');
if (menuCurrent) { menuCurrent.click(); return; }
// fallback: force HTMX to reload the current fragment
var frag = document.getElementById('question-fragment');
if (frag && frag.getAttribute('hx-get')) {
htmx.trigger(frag, 'load');
}
});
})();
</script>
</div>