Enhance exam navigation by adding a skip button for non-saving question transitions and implementing unsaved changes confirmation.
This commit is contained in:
@@ -61,6 +61,12 @@
|
|||||||
|
|
||||||
{% if next %}
|
{% 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 %}
|
{% else %}
|
||||||
{% if not exam.publish_results %}
|
{% 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>
|
<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;
|
document.getElementById('goto-button').value = e.currentTarget.dataset.qn;
|
||||||
$('#goto-button').click();
|
$('#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>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user