Enhance question menu state management by adding a centralized updater for answered and flagged questions
This commit is contained in:
@@ -53,6 +53,21 @@
|
|||||||
// Minimal per-question status injected by view: answered/flagged arrays
|
// Minimal per-question status injected by view: answered/flagged arrays
|
||||||
window.examQuestionAnswered = {{ answered_json|safe }};
|
window.examQuestionAnswered = {{ answered_json|safe }};
|
||||||
window.examQuestionFlagged = {{ flagged_json|safe }};
|
window.examQuestionFlagged = {{ flagged_json|safe }};
|
||||||
|
// Update the visual state of the question menu based on global arrays
|
||||||
|
window.updateQuestionMenu = function(){
|
||||||
|
try{
|
||||||
|
const answered = window.examQuestionAnswered || [];
|
||||||
|
const flagged = window.examQuestionFlagged || [];
|
||||||
|
const pos = (typeof window.currentQuestionPos === 'number') ? window.currentQuestionPos : NaN;
|
||||||
|
document.querySelectorAll('#menu-list .question-menu-item').forEach(btn => {
|
||||||
|
const idx = parseInt(btn.dataset.qn, 10);
|
||||||
|
btn.classList.toggle('answered', !!answered[idx]);
|
||||||
|
btn.classList.toggle('flagged', !!flagged[idx]);
|
||||||
|
btn.classList.toggle('current-question', idx === pos);
|
||||||
|
// ensure text colour remains white (use CSS var) - no-op if CSS already set
|
||||||
|
});
|
||||||
|
}catch(e){ console && console.error && console.error(e); }
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{% include "physics/exam_take_help.html" %}
|
{% include "physics/exam_take_help.html" %}
|
||||||
@@ -304,9 +319,13 @@
|
|||||||
if (!isNaN(pos)) {
|
if (!isNaN(pos)) {
|
||||||
window.examQuestionAnswered = window.examQuestionAnswered || new Array({{ exam_length }}).fill(false);
|
window.examQuestionAnswered = window.examQuestionAnswered || new Array({{ exam_length }}).fill(false);
|
||||||
window.examQuestionAnswered[pos] = true;
|
window.examQuestionAnswered[pos] = true;
|
||||||
|
if(typeof window.updateQuestionMenu === 'function'){
|
||||||
|
window.updateQuestionMenu();
|
||||||
|
} else {
|
||||||
var btn = document.querySelector('#menu-list [data-qn="' + pos + '"]');
|
var btn = document.querySelector('#menu-list [data-qn="' + pos + '"]');
|
||||||
if (btn) btn.classList.add('answered');
|
if (btn) btn.classList.add('answered');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (e) { console && console.error && console.error(e); }
|
} catch (e) { console && console.error && console.error(e); }
|
||||||
} catch (e) { console && console.error && console.error(e); }
|
} catch (e) { console && console.error && console.error(e); }
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -99,7 +99,7 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
<style>
|
<style>
|
||||||
/* Overview page specific styles */
|
/* Overview page specific styles */
|
||||||
.overview-text {
|
.overview-text {
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
@@ -165,5 +165,5 @@
|
|||||||
}
|
}
|
||||||
.overview-question-btn { font-size: .95rem }
|
.overview-question-btn { font-size: .95rem }
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -138,17 +138,19 @@
|
|||||||
const flaggedArr = (window.examQuestionFlagged && Array.isArray(window.examQuestionFlagged)) ? window.examQuestionFlagged : null;
|
const flaggedArr = (window.examQuestionFlagged && Array.isArray(window.examQuestionFlagged)) ? window.examQuestionFlagged : null;
|
||||||
for (let i = 0; i < {{ exam_length }}; i++) {
|
for (let i = 0; i < {{ exam_length }}; i++) {
|
||||||
const qbutton = $(`<button class="question-menu-item" name="goto-${i}" data-qn="${i}"><span class="qnum">${i+1}</span></button>`);
|
const qbutton = $(`<button class="question-menu-item" name="goto-${i}" data-qn="${i}"><span class="qnum">${i+1}</span></button>`);
|
||||||
// answered: indicate with border colour but keep text colour unchanged (white)
|
|
||||||
if (answeredArr && answeredArr[i]) { qbutton.addClass('answered'); }
|
if (answeredArr && answeredArr[i]) { qbutton.addClass('answered'); }
|
||||||
// flagged: add flag icon and flagged class which alters border
|
|
||||||
if (flaggedArr && flaggedArr[i]) {
|
if (flaggedArr && flaggedArr[i]) {
|
||||||
qbutton.addClass('flagged');
|
qbutton.addClass('flagged');
|
||||||
qbutton.append('<span class="question-flag" aria-hidden="true">⚑</span>');
|
// ensure flag icon exists only once
|
||||||
|
if (qbutton.find('.question-flag').length === 0) qbutton.append('<span class="question-flag" aria-hidden="true">⚑</span>');
|
||||||
}
|
}
|
||||||
if (i == {{ pos }}) { qbutton.addClass('current-question'); }
|
if (i == {{ pos }}) { qbutton.addClass('current-question'); }
|
||||||
$('#menu-list').append(qbutton);
|
$('#menu-list').append(qbutton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Let a central updater ensure classes are consistent (handles cases where menu exists before arrays)
|
||||||
|
if(typeof window.updateQuestionMenu === 'function') window.updateQuestionMenu();
|
||||||
|
|
||||||
// Template URL for loading a fragment — use sk=0 as placeholder to replace later
|
// Template URL for loading a fragment — use sk=0 as placeholder to replace later
|
||||||
const fragUrlTemplate = `{% if cid %}{% url 'physics:exam_take_fragment' pk=exam.pk sk=0 cid=cid passcode=passcode %}{% else %}{% url 'physics:exam_take_fragment_user' pk=exam.pk sk=0 %}{% endif %}`;
|
const fragUrlTemplate = `{% if cid %}{% url 'physics:exam_take_fragment' pk=exam.pk sk=0 cid=cid passcode=passcode %}{% else %}{% url 'physics:exam_take_fragment_user' pk=exam.pk sk=0 %}{% endif %}`;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user