diff --git a/physics/templates/physics/exam_take.html b/physics/templates/physics/exam_take.html index f617a2d0..8af452fa 100755 --- a/physics/templates/physics/exam_take.html +++ b/physics/templates/physics/exam_take.html @@ -12,10 +12,15 @@ {% include "exam_clock.html" %}
-

- {{ exam }}: Question - [{{ pos|add:1 }}/{{ exam_length }}] -

+
+

+ {{ exam }}: Question + [{{ pos|add:1 }}/{{ exam_length }}] +

+
+ {% include 'physics/partials/exam_flag_button.html' %} +
+
{% if exam.publish_results %}
-
- {% include 'physics/partials/exam_flag_button.html' %} -
{% if previous > -1 %} {% endif %} @@ -153,36 +150,69 @@ }); if(allFalse){ - const save = confirm('All answers are false. OK to save these answers, Cancel to skip without saving.'); - if(save){ - const form = document.querySelector('.post-form'); - if(form){ - const tmp = document.createElement('button'); tmp.type='submit'; tmp.name='save'; tmp.style.display='none'; form.appendChild(tmp); - const onSaved = function(){ document.removeEventListener('saved', onSaved); document.getElementById('goto-button').value = destIndex; $('#goto-button').click(); }; - document.addEventListener('saved', onSaved); - tmp.click(); - setTimeout(function(){ document.removeEventListener('saved', onSaved); document.getElementById('goto-button').value = destIndex; $('#goto-button').click(); }, 1500); - return; - } - } - - // Skip without saving: load fragment directly via HTMX and update URL + // Use modal prompt instead of native confirm try{ - const url = fragUrlTemplate.replace('/0/', '/' + destIndex + '/'); - if(window.htmx && typeof htmx.ajax === 'function'){ - htmx.ajax('GET', url, {target: '#question-fragment', swap: 'innerHTML'}); - } else { - window.location.href = url; + // prevent default while we prompt + e.preventDefault(); e.stopImmediatePropagation(); + }catch(ex){} + openSaveSkipModal('All answers are false. Save these answers or skip without saving?').then(function(choice){ + if(choice === 'save'){ + const form = document.querySelector('.post-form'); + if(form){ + const tmp = document.createElement('button'); tmp.type='submit'; tmp.name='save'; tmp.style.display='none'; form.appendChild(tmp); + + // One-time htmx listener to detect the save response and then navigate + let handled = false; + function htmxHandler(evt){ + try{ + const xhr = evt.detail.xhr; + const hxTrigger = xhr && xhr.getResponseHeader && xhr.getResponseHeader('HX-Trigger'); + if(hxTrigger && hxTrigger.indexOf('saved') !== -1){ + handled = true; + if(window.htmx && typeof htmx.off === 'function') htmx.off('htmx:afterRequest', htmxHandler); + document.getElementById('goto-button').value = destIndex; + $('#goto-button').click(); + } + }catch(e){/* ignore */} + } + + if(window.htmx && typeof htmx.on === 'function'){ + htmx.on('htmx:afterRequest', htmxHandler); + } + + // As a fallback listen for the custom 'saved' event + const onSavedFallback = function(){ if(handled) return; handled = true; document.removeEventListener('saved', onSavedFallback); document.getElementById('goto-button').value = destIndex; $('#goto-button').click(); }; + document.addEventListener('saved', onSavedFallback); + + tmp.click(); + + // final timeout fallback + setTimeout(function(){ if(!handled){ try{ document.removeEventListener('saved', onSavedFallback); if(window.htmx && typeof htmx.off === 'function') htmx.off('htmx:afterRequest', htmxHandler); document.getElementById('goto-button').value = destIndex; $('#goto-button').click(); }catch(e){} } }, 1500); + return; + } } - // update browser URL to match the question destination + + // skip or cancel -> load fragment directly via HTMX and update URL try{ - const pageUrl = `{% if cid %}{% url 'physics:exam_take' pk=exam.pk sk=0 cid=cid passcode=passcode %}{% else %}{% url 'physics:exam_take_user' pk=exam.pk sk=0 %}{% endif %}`.replace('/0/', '/' + destIndex + '/'); - history.replaceState(null, '', pageUrl); - }catch(e){} - }catch(e){ + const url = fragUrlTemplate.replace('/0/', '/' + destIndex + '/'); + if(window.htmx && typeof htmx.ajax === 'function'){ + htmx.ajax('GET', url, {target: '#question-fragment', swap: 'innerHTML'}); + } else { + window.location.href = url; + } + try{ + const pageUrl = `{% if cid %}{% url 'physics:exam_take' pk=exam.pk sk=0 cid=cid passcode=passcode %}{% else %}{% url 'physics:exam_take_user' pk=exam.pk sk=0 %}{% endif %}`.replace('/0/', '/' + destIndex + '/'); + history.replaceState(null, '', pageUrl); + }catch(e){} + }catch(e){ + document.getElementById('goto-button').value = destIndex; + $('#goto-button').click(); + } + }).catch(function(){ + // on error, fallback to navigation document.getElementById('goto-button').value = destIndex; $('#goto-button').click(); - } + }); return; } }catch(ex){ console && console.error && console.error(ex); }