Enhance exam navigation by adding a skip button for non-saving question transitions and implementing unsaved changes confirmation.
This commit is contained in:
@@ -60,7 +60,13 @@
|
||||
{% endif %}
|
||||
|
||||
{% if next %}
|
||||
<button type="submit" name="next" class="save btn btn-secondary" title="Click to save your answer(s) and go to the next question">Next</button>
|
||||
<button type="submit" name="next" class="save btn btn-secondary" title="Click to save your answer(s) and go to the next question">Next</button>
|
||||
<!-- Skip: load the next question fragment without submitting the form -->
|
||||
<button type="button" id="skip-button" class="btn btn-outline-secondary ms-2" title="Skip to next question without saving"
|
||||
hx-get="{% if cid %}{% url 'physics:exam_take_fragment' pk=exam.pk sk=pos|add:1 cid=cid passcode=passcode %}{% else %}{% url 'physics:exam_take_fragment_user' pk=exam.pk sk=pos|add:1 %}{% endif %}"
|
||||
hx-target="#question-fragment" hx-swap="innerHTML">Skip</button>
|
||||
<!-- Fallback link for non-HTMX clients: simple navigation without saving -->
|
||||
<a class="d-none" href="{% if cid %}{% url 'physics:exam_take' pk=exam.pk sk=pos|add:1 cid=cid passcode=passcode %}{% else %}{% url 'physics:exam_take_user' pk=exam.pk sk=pos|add:1 %}{% endif %}"></a>
|
||||
{% else %}
|
||||
{% if not exam.publish_results %}
|
||||
<button type="submit" name="save" class="save btn btn-default" title="Click to save your current answer(s)">Save</button>
|
||||
@@ -128,6 +134,58 @@
|
||||
document.getElementById('goto-button').value = e.currentTarget.dataset.qn;
|
||||
$('#goto-button').click();
|
||||
});
|
||||
|
||||
// Skip confirmation: if the user's current selections differ from
|
||||
// the saved answer, prompt before allowing the HTMX skip to proceed.
|
||||
(function(){
|
||||
const skip = document.getElementById('skip-button');
|
||||
if(!skip) return;
|
||||
|
||||
// Build a JS array of saved answers (booleans) or null
|
||||
{% if saved_answer %}
|
||||
const savedAnswers = [{% for s in saved_answer %}{{ s|yesno:"true,false" }}{% if not forloop.last %}, {% endif %}{% endfor %}];
|
||||
{% else %}
|
||||
const savedAnswers = null;
|
||||
{% endif %}
|
||||
|
||||
function readCurrent(){
|
||||
const lis = document.querySelectorAll('ol.physics-answer-list li');
|
||||
return Array.from(lis).map(li => {
|
||||
const inp = li.querySelector('input');
|
||||
return !!(inp && inp.checked);
|
||||
});
|
||||
}
|
||||
|
||||
skip.addEventListener('click', function(evt){
|
||||
try{
|
||||
const current = readCurrent();
|
||||
let changed = false;
|
||||
if(savedAnswers === null){
|
||||
// no previously-saved answer; any current selection is a change
|
||||
changed = current.some(Boolean);
|
||||
} else {
|
||||
if(current.length === savedAnswers.length){
|
||||
for(let i=0;i<current.length;i++){
|
||||
if(!!current[i] !== !!savedAnswers[i]){ changed = true; break; }
|
||||
}
|
||||
} else {
|
||||
// differing lengths — consider changed if any selection present
|
||||
changed = current.some(Boolean);
|
||||
}
|
||||
}
|
||||
|
||||
if(changed){
|
||||
const ok = confirm('You have unsaved changes. Skip to the next question without saving?');
|
||||
if(!ok){
|
||||
// prevent HTMX from handling the click
|
||||
evt.preventDefault(); evt.stopImmediatePropagation();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// allow the HTMX attribute on the button to proceed
|
||||
}catch(e){ console && console.error && console.error(e); }
|
||||
});
|
||||
})();
|
||||
})();
|
||||
</script>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user