Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 34 additions & 18 deletions quiz/projectilequiz.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@
<link rel="stylesheet" href="../variables.css">
<script src="../theme.js"></script>
<link rel="stylesheet" href="projectilequiz.css">
<link rel="manifest" href="manifest.json">
<meta name="theme-color" content="#0f1115">
</head>

<body>

<div class="container">
<a class="skip-link" href="#content">Skip to content</a>

<div class="container" id="content">

<h1 class="title">Physics Projectile Motion Quiz 🎯</h1>
<p class="description">Test your knowledge of motion concepts!</p>

Expand All @@ -21,34 +26,45 @@ <h1 class="title">Physics Projectile Motion Quiz 🎯</h1>
<div id="progress-bar"></div>
</div>

<div id="quiz-box">
<main id="quiz-box" role="group" aria-label="Quiz">
<h2 id="question">Loading...</h2>
<div id="options" class="options-grid"></div>
<button id="prev-btn" onclick="prevQuestion()" disabled>Previous</button>
<button id="next-btn" onclick="nextQuestion()" disabled>Next</button>
<button id="submit-btn" class="hidden" onclick="confirmSubmit()">Submit</button>
</div>
<div id="options" class="options-grid" role="radiogroup" aria-labelledby="question"></div>
<div class="button-group" role="group" aria-label="Quiz navigation">
<button id="prev-btn" onclick="prevQuestion()" disabled aria-label="Previous question">Previous</button>
<button id="next-btn" onclick="nextQuestion()" disabled aria-label="Next question">Next</button>
<button id="submit-btn" class="hidden" onclick="confirmSubmit()" aria-label="Submit quiz">Submit</button>
</div>
<p id="sr-status" class="sr-only" aria-live="polite" aria-atomic="true"></p>
</main>


<!-- Warning Popup -->
<div id="popup" class="popup hidden">
<h3>⚠️ Please select an answer before proceeding!</h3>
<button onclick="closePopup()">OK</button>
<div id="popup" class="popup hidden" role="dialog" aria-modal="true" aria-labelledby="popup-title">
<h3 id="popup-title">⚠️ Please select an answer before proceeding!</h3>
<button id="popup-ok" onclick="closePopup()" aria-label="Close warning">OK</button>
</div>

<!-- Confirm Submit Popup -->
<div id="confirm-popup" class="popup hidden">
<h3>Are you sure you want to submit?</h3>
<button onclick="submitQuiz()">Yes, Submit</button>
<button onclick="closeConfirmPopup()">No, Resume</button>
<div id="confirm-popup" class="popup hidden" role="dialog" aria-modal="true" aria-labelledby="confirm-popup-title">
<h3 id="confirm-popup-title">Are you sure you want to submit?</h3>
<button id="confirm-yes" onclick="submitQuiz()" aria-label="Confirm submit">Yes, Submit</button>
<button id="confirm-no" onclick="closeConfirmPopup()" aria-label="Cancel submit">No, Resume</button>
</div>



<!-- Result Box -->
<div id="result-box" class="hidden">
<h2>🎉 Quiz Completed!</h2>
<div id="result-box" class="hidden" aria-labelledby="result-heading">
<h2 tabindex="-1" id="result-heading">🎉 Quiz Completed!</h2>
<p id="score"></p>
<button onclick="restartQuiz()">Try Again 🔄</button>
<button class="motion"><a href="..\projectile\projectile.html">⬅ Back to Previous Page</a></button>
<div class="button-group" role="group" aria-label="Quiz results actions">
<button onclick="restartQuiz()">Try Again 🔄</button>
<button class="motion" aria-label="Back to previous page">
<a href="..\projectile\projectile.html">⬅ Back</a>
</button>
</div>
</div>

</div>

<script src="../quizProgress.js"></script>
Expand Down
151 changes: 149 additions & 2 deletions quiz/projectilequiz.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,45 @@ let score = 0;
let selectedOption = null;
let userSelectionsByStep = [];

let lastFocusedEl = null;

function getSrStatus() {
return document.getElementById("sr-status");
}

function announce(message) {
const el = getSrStatus();
if (!el) return;
el.textContent = message;
}

function loadQuestion() {
lastFocusedEl = document.activeElement;

let questionData = questions[currentQuestionIndex];
document.getElementById("question").textContent = questionData.question;

let optionsContainer = document.getElementById("options");
optionsContainer.innerHTML = "";

questionData.options.forEach(option => {
// Announce current question for screen readers
announce(`Question ${currentQuestionIndex + 1} of ${questions.length}. ${questionData.question}`);


questionData.options.forEach((option) => {
let btn = document.createElement("button");
btn.classList.add("option");
btn.type = "button";
btn.textContent = option;

btn.setAttribute("role", "radio");
btn.setAttribute("aria-checked", "false");

btn.onclick = () => selectOption(btn, option);
optionsContainer.appendChild(btn);
});


selectedOption = null;
document.getElementById("next-btn").disabled = true;
document.getElementById("prev-btn").disabled = currentQuestionIndex === 0;
Expand All @@ -39,13 +62,22 @@ function loadQuestion() {
}

function selectOption(button, option) {
document.querySelectorAll(".option").forEach(btn => btn.classList.remove("selected"));
document.querySelectorAll(".option").forEach((btn) => {
btn.classList.remove("selected");
btn.setAttribute("aria-checked", "false");
});

button.classList.add("selected");
button.setAttribute("aria-checked", "true");

selectedOption = option;
userAnswers[currentQuestionIndex] = option;
document.getElementById("next-btn").disabled = false;

announce(`Selected: ${option}`);
}


function nextQuestion() {
if (!selectedOption) {
showPopup();
Expand Down Expand Up @@ -99,27 +131,49 @@ function restartQuiz() {
document.getElementById("progress-bar").style.width = "0%";

loadQuestion();

setTimeout(() => {
const firstOption = document.querySelector("#options .option");
if (firstOption) firstOption.focus();
}, 0);
}


function showPopup() {
lastFocusedEl = document.activeElement;
document.getElementById("popup").style.display = "block";

const okBtn = document.getElementById("popup-ok");
if (okBtn) okBtn.focus();

announce("Warning: Please select an answer before proceeding.");
}

function closePopup() {
document.getElementById("popup").style.display = "none";
if (lastFocusedEl && typeof lastFocusedEl.focus === "function") lastFocusedEl.focus();
}

function closeConfirmPopup() {
document.getElementById("confirm-popup").style.display = "none";
if (lastFocusedEl && typeof lastFocusedEl.focus === "function") lastFocusedEl.focus();
}


function showResults() {
document.getElementById("quiz-box").classList.add("hidden");
document.getElementById("result-box").classList.remove("hidden");

const heading = document.getElementById("result-heading");
if (heading) heading.focus();

let scoreText = `You scored <strong>${score}</strong> out of ${questions.length}! 🎉`;


let feedbackHTML = "";



questions.forEach((q, index) => {
let userAnswer = userAnswers[index] || "No answer selected";
let isCorrect = userAnswer === q.answer;
Expand All @@ -135,14 +189,107 @@ function showResults() {
});

document.getElementById("score").innerHTML = scoreText + "<br><br>" + feedbackHTML;

announce(`Quiz completed. Score: ${score} out of ${questions.length}.`);
}







function updateProgressBar() {
let progress = ((currentQuestionIndex + 1) / questions.length) * 100;

document.getElementById("progress-bar").style.width = progress + "%";
}

function getOptionButtons() {
return Array.from(document.querySelectorAll("#options .option"));
}

function moveOptionFocus(delta) {
const options = getOptionButtons();
if (options.length === 0) return;

const active = document.activeElement;
let idx = options.indexOf(active);
if (idx === -1) {
idx = selectedOption ? options.findIndex((b) => b.textContent === selectedOption) : 0;
if (idx < 0) idx = 0;
}

const nextIdx = Math.max(0, Math.min(options.length - 1, idx + delta));
options[nextIdx].focus();
}

document.addEventListener("keydown", (e) => {
const quizBox = document.getElementById("quiz-box");
if (!quizBox || quizBox.classList.contains("hidden")) return;

const options = getOptionButtons();
const active = document.activeElement;
const isOptionFocused = options.includes(active);

if (e.key === "Escape") {
const popup = document.getElementById("popup");
const confirmPopup = document.getElementById("confirm-popup");
if (popup && popup.style.display !== "none" && !popup.classList.contains("hidden")) {
e.preventDefault();
closePopup();
return;
}
if (confirmPopup && confirmPopup.style.display !== "none" && !confirmPopup.classList.contains("hidden")) {
e.preventDefault();
closeConfirmPopup();
return;
}
}

if (e.key === "ArrowRight" || e.key === "ArrowDown") {
e.preventDefault();
moveOptionFocus(1);
return;
}

if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
e.preventDefault();
moveOptionFocus(-1);
return;
}

if (e.key === "Enter" || e.key === " ") {
if (isOptionFocused) {
e.preventDefault();
const optionText = active.textContent;
if (optionText) selectOption(active, optionText);
return;
}

if (selectedOption) {
const submitHidden = document.getElementById("submit-btn").classList.contains("hidden");
if (!submitHidden) {
e.preventDefault();
confirmSubmit();
} else {
const nextBtn = document.getElementById("next-btn");
if (nextBtn && !nextBtn.disabled) {
e.preventDefault();
nextQuestion();
}
}
}
}
});

document.addEventListener("DOMContentLoaded", () => {
document.getElementById("progress-bar").style.width = "0%";
loadQuestion();

setTimeout(() => {
const firstOption = document.querySelector("#options .option");
if (firstOption) firstOption.focus();
}, 0);
});

Loading
Loading