Add HTMX support for exam overview fragment to enhance user experience
This commit is contained in:
@@ -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>
|
||||
Reference in New Issue
Block a user