Trivia Quiz Maker

Trivia Quiz Maker

Welcome to the trivia quiz! Press Start when ready.

Add New Question

Current Questions

"; return; } quizData.forEach((q) => { const item = document.createElement("div"); item.className = "tqm-question-item"; item.innerHTML = `

${escapeHTML(q.question)}

`; questionList.appendChild(item); }); // Add event listeners to new buttons questionList.querySelectorAll(".tqm-edit-btn").forEach((btn) => { btn.addEventListener("click", () => handleEditClick(btn.dataset.id)); }); questionList .querySelectorAll(".tqm-delete-btn") .forEach((btn) => { btn.addEventListener("click", () => handleDeleteClick(btn.dataset.id) ); }); } /** * Handles the form submission for adding or updating a question. */ function handleFormSubmit(e) { e.preventDefault(); const questionText = questionTextInput.value.trim(); const options = optionInputs.map((input) => input.value.trim()); const correctIndex = parseInt(correctAnswerSelect.value, 10); const id = questionIdInput.value; if (!questionText || options.some((opt) => !opt)) { alert("Please fill out the question and all four options."); return; } if (id) { // Update existing const index = quizData.findIndex((q) => q.id == id); if (index !== -1) { quizData[index] = { id: Number(id), question: questionText, options, correctIndex }; } } else { // Add new quizData.push({ id: Date.now(), question: questionText, options, correctIndex, }); } resetForm(); renderQuestionList(); initQuiz(); // Update the quiz in Tab 1 } /** * Resets the question form. */ function resetForm() { formTitle.textContent = "Add New Question"; questionIdInput.value = ""; questionForm.reset(); saveQuestionBtn.textContent = "Save Question"; } /** * Populates the form with a question's data for editing. */ function handleEditClick(id) { const question = quizData.find((q) => q.id == id); if (!question) return; formTitle.textContent = "Edit Question"; questionIdInput.value = question.id; questionTextInput.value = question.question; optionInputs.forEach( (input, index) => (input.value = question.options[index]) ); correctAnswerSelect.value = question.correctIndex; saveQuestionBtn.textContent = "Update Question"; questionTextInput.focus(); } /** * Deletes a question from the quiz. */ function handleDeleteClick(id) { if (confirm("Are you sure you want to delete this question?")) { quizData = quizData.filter((q) => q.id != id); renderQuestionList(); initQuiz(); // Update the quiz in Tab 1 } } // --- Tab 1: Quiz Taker Logic --- /** * Initializes the quiz, resets state, and shows the start screen. */ function initQuiz() { currentQuestionIndex = 0; userScore = 0; userAnswers = []; if (quizData.length === 0) { quizIntro.textContent = "No quiz questions have been configured yet. Please go to the 'Quiz Configuration' tab to add questions."; startBtn.disabled = true; } else { quizIntro.textContent = `This quiz has ${quizData.length} question(s). Press Start when ready.`; startBtn.disabled = false; } startScreen.style.display = "block"; questionScreen.style.display = "none"; resultsScreen.style.display = "none"; } /** * Starts the quiz, hiding the start screen and showing the first question. */ function startQuiz() { startScreen.style.display = "none"; questionScreen.style.display = "block"; showQuestion(); } /** * Displays the current question and its options. */ function showQuestion() { if (!quizQuestion || !quizOptions || !quizProgress) return; // Clear previous state quizFeedback.style.display = "none"; nextQuestionBtn.style.display = "none"; const q = quizData[currentQuestionIndex]; quizQuestion.textContent = q.question; quizProgress.textContent = `Question ${currentQuestionIndex + 1} of ${ quizData.length }`; quizOptions.innerHTML = ""; // Clear old options q.options.forEach((option, index) => { const button = document.createElement("button"); button.type = "button"; button.className = "tqm-quiz-option"; button.textContent = escapeHTML(option); button.dataset.index = index; button.addEventListener("click", handleOptionClick); quizOptions.appendChild(button); }); } /** * Handles the user clicking an answer option. */ function handleOptionClick(e) { const selectedIndex = parseInt(e.target.dataset.index, 10); const q = quizData[currentQuestionIndex]; const correctIndex = q.correctIndex; // Disable all option buttons quizOptions.querySelectorAll(".tqm-quiz-option").forEach((btn) => { btn.disabled = true; }); // Store answer for summary userAnswers.push({ question: q.question, selectedAnswer: q.options[selectedIndex], correctAnswer: q.options[correctIndex], isCorrect: selectedIndex === correctIndex, }); if (selectedIndex === correctIndex) { // Correct userScore++; e.target.classList.add("correct"); quizFeedback.textContent = "Correct!"; quizFeedback.className = "correct"; } else { // Incorrect e.target.classList.add("incorrect"); quizFeedback.textContent = "Incorrect!"; quizFeedback.className = "incorrect"; // Highlight the correct answer quizOptions .querySelector(`.tqm-quiz-option[data-index="${correctIndex}"]`) .classList.add("correct"); } quizFeedback.style.display = "block"; nextQuestionBtn.style.display = "inline-block"; // Update "Next" button text if last question if (currentQuestionIndex === quizData.length - 1) { nextQuestionBtn.textContent = "Show Results"; } else { nextQuestionBtn.textContent = "Next Question"; } } /** * Handles click on "Next Question" or "Show Results" button. */ function handleNextClick() { currentQuestionIndex++; if (currentQuestionIndex < quizData.length) { showQuestion(); } else { showResults(); } } /** * Displays the final results screen. */ function showResults() { questionScreen.style.display = "none"; resultsScreen.style.display = "block"; quizScore.textContent = `You got ${userScore} out of ${quizData.length} correct! (${( (userScore / quizData.length) * 100 ).toFixed(0)}%)`; renderResultsSummary(); } /** * Renders the detailed summary of answers. */ function renderResultsSummary() { if (!quizSummary) return; quizSummary.innerHTML = ""; userAnswers.forEach((answer, index) => { const item = document.createElement('div'); item.className = 'tqm-summary-item'; let answerHTML = ''; if (answer.isCorrect) { answerHTML = `
Your answer: ${escapeHTML(answer.selectedAnswer)} (Correct)
`; } else { answerHTML = `
Your answer: ${escapeHTML(answer.selectedAnswer)} (Incorrect)
Correct answer: ${escapeHTML(answer.correctAnswer)}
`; } item.innerHTML = `
Q${index+1}: ${escapeHTML(answer.question)}
${answerHTML} `; quizSummary.appendChild(item); }); } /** * Generates and downloads a PDF of the quiz results. */ function downloadPDF() { if (typeof jsPDF === "undefined") { alert("Error: PDF generation library failed to load."); return; } try { const doc = new jsPDF(); const pageMargin = 20; const pageWidth = doc.internal.pageSize.getWidth() - pageMargin * 2; let yPos = 25; const title = "Quiz Results"; const score = `Final Score: ${userScore} out of ${quizData.length} (${( (userScore / quizData.length) * 100 ).toFixed(0)}%)`; doc.setFont("helvetica", "bold"); doc.setFontSize(18); doc.setTextColor("#34495e"); doc.text(title, pageMargin, yPos); yPos += 10; doc.setFontSize(14); doc.setTextColor("#333333"); doc.text(score, pageMargin, yPos); yPos += 15; userAnswers.forEach((answer, index) => { const qText = `Q${index + 1}: ${answer.question}`; const aTextUser = `Your answer: ${answer.selectedAnswer}`; const aTextCorrect = `Correct answer: ${answer.correctAnswer}`; // Check for page break if (yPos > 260) { doc.addPage(); yPos = 20; } doc.setFont("helvetica", "bold"); doc.setFontSize(12); doc.setTextColor("#34495e"); const qLines = doc.splitTextToSize(qText, pageWidth); doc.text(qLines, pageMargin, yPos); yPos += (qLines.length * 5) + 2; // Adjust Y pos for lines doc.setFont("helvetica", "normal"); doc.setFontSize(11); if (answer.isCorrect) { doc.setTextColor("#155724"); // Green doc.text(`${aTextUser} (Correct)`, pageMargin + 5, yPos); yPos += 10; } else { doc.setTextColor("#721c24"); // Red doc.text(`${aTextUser} (Incorrect)`, pageMargin + 5, yPos); yPos += 7; doc.setTextColor("#333333"); doc.text(aTextCorrect, pageMargin + 5, yPos); yPos += 10; } yPos += 5; // Extra spacing }); doc.save("Trivia-Quiz-Results.pdf"); } catch (error) { console.error("Failed to generate PDF:", error); alert("An error occurred while generating the PDF."); } } /** * Utility to escape HTML for safe rendering. */ function escapeHTML(str) { return str .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } /** * Loads sample data (USA-based). */ function loadSampleData() { quizData = [ { id: 1, question: "What is the capital of California?", options: ["Los Angeles", "Sacramento", "San Francisco", "San Diego"], correctIndex: 1 }, { id: 2, question: "Which U.S. state is known as the 'Sunshine State'?", options: ["Arizona", "Texas", "Florida", "Hawaii"], correctIndex: 2 } ]; } // --- Event Listeners --- if (tabButtons[1]) tabButtons[1].onclick = () => showTab(1); if (tabButtons[2]) tabButtons[2].onclick = () => showTab(2); if (prevBtn) prevBtn.onclick = () => showTab(currentTab - 1); if (nextBtn) nextBtn.onclick = () => showTab(currentTab + 1); // Tab 1 Listeners if (startBtn) startBtn.addEventListener("click", startQuiz); if (nextQuestionBtn) nextQuestionBtn.addEventListener("click", handleNextClick); if (restartBtn) restartBtn.addEventListener("click", initQuiz); if (downloadPdfBtn) downloadPdfBtn.addEventListener("click", downloadPDF); // Tab 2 Listeners if (questionForm) questionForm.addEventListener("submit", handleFormSubmit); if (clearFormBtn) clearFormBtn.addEventListener("click", resetForm); // --- Initialization --- function init() { loadSampleData(); renderQuestionList(); initQuiz(); showTab(1); // Set initial tab state } init(); });