Basic Vocabulary Builder

Basic Vocabulary Builder

My Word List Dashboard

This is a complete list of all vocabulary words you have added. You can download this list as a PDF.

Flashcard Practice

Start practicing your words. Add words in the "Data Configuration" tab.

Quiz Mode

Test your knowledge! The quiz will ask for the definition of a random word from your list.

Data Configuration

Add a New Word

Manage My Word List

`).join(''); } /** * Handles adding a new word from the form */ function addBvbWord(e) { e.preventDefault(); const word = bvbNewWord.value.trim(); const definition = bvbNewDefinition.value.trim(); const sentence = bvbNewSentence.value.trim(); if (word && definition) { bvbWordList.push({ word, definition, sentence }); bvbNewWord.value = ''; bvbNewDefinition.value = ''; bvbNewSentence.value = ''; renderAllBvbContent(); } } /** * Handles deleting a word */ function deleteBvbWord(index) { bvbWordList.splice(index, 1); renderAllBvbContent(); } // --- 4. FLASHCARD FUNCTIONS (Tab 2) --- function resetBvbFlashcard() { bvbFlashcardStartScreen.style.display = 'block'; bvbFlashcardActiveScreen.style.display = 'none'; bvbFlashcardStartBtn.disabled = bvbWordList.length === 0; } function startBvbFlashcards() { if (bvbWordList.length === 0) return; bvbFlashcardStartScreen.style.display = 'none'; bvbFlashcardActiveScreen.style.display = 'block'; bvbFlashcardIndex = 0; showBvbFlashcard(bvbFlashcardIndex); } function showBvbFlashcard(index) { const item = bvbWordList[index]; bvbFlashcardWord.textContent = item.word; bvbFlashcardDefinition.textContent = item.definition; bvbFlashcardSentence.textContent = item.sentence || ''; bvbFlashcardAnswer.style.display = 'none'; // Hide answer bvbFlashcardFlipBtn.textContent = 'Flip Card'; } function flipBvbCard() { const isHidden = bvbFlashcardAnswer.style.display === 'none'; bvbFlashcardAnswer.style.display = isHidden ? 'block' : 'none'; bvbFlashcardFlipBtn.textContent = isHidden ? 'Hide Answer' : 'Flip Card'; } function nextBvbFlashcard() { bvbFlashcardIndex = (bvbFlashcardIndex + 1) % bvbWordList.length; showBvbFlashcard(bvbFlashcardIndex); } // --- 5. QUIZ FUNCTIONS (Tab 3) --- function resetBvbQuiz() { bvbQuizStartScreen.style.display = 'block'; bvbQuizActiveScreen.style.display = 'none'; bvbQuizResultsScreen.style.display = 'none'; bvbQuizStartBtn.disabled = bvbWordList.length === 0; } function startBvbQuiz() { if (bvbWordList.length === 0) return; // Create a shuffled quiz list const shuffledList = [...bvbWordList].sort(() => 0.5 - Math.random()); bvbQuizState = { questions: shuffledList, currentQuestionIndex: 0, score: 0 }; bvbQuizStartScreen.style.display = 'none'; bvbQuizActiveScreen.style.display = 'block'; bvbQuizResultsScreen.style.display = 'none'; bvbQuizFeedback.innerHTML = ''; bvbQuizAnswer.value = ''; showBvbQuizQuestion(); } function showBvbQuizQuestion() { if (bvbQuizState.currentQuestionIndex >= bvbQuizState.questions.length) { showBvbQuizResults(); return; } const question = bvbQuizState.questions[bvbQuizState.currentQuestionIndex]; bvbQuizProgress.textContent = `Question ${bvbQuizState.currentQuestionIndex + 1} of ${bvbQuizState.questions.length}`; bvbQuizQuestion.textContent = `What is the definition of: "${question.word}"?`; bvbQuizAnswer.value = ''; bvbQuizFeedback.innerHTML = ''; bvbQuizSubmitBtn.textContent = 'Submit Answer'; bvbQuizSubmitBtn.onclick = checkBvbAnswer; // Assign click handler } function checkBvbAnswer() { const userAnswer = bvbQuizAnswer.value.trim().toLowerCase(); const correctAnswer = bvbQuizState.questions[bvbQuizState.currentQuestionIndex].definition.trim().toLowerCase(); if (userAnswer === correctAnswer) { bvbQuizFeedback.textContent = "Correct!"; bvbQuizFeedback.className = 'bvb-feedback-correct'; bvbQuizState.score++; } else { bvbQuizFeedback.textContent = `Incorrect. The correct answer is: "${bvbQuizState.questions[bvbQuizState.currentQuestionIndex].definition}"`; bvbQuizFeedback.className = 'bvb-feedback-incorrect'; } bvbQuizState.currentQuestionIndex++; bvbQuizSubmitBtn.textContent = 'Next Question'; bvbQuizSubmitBtn.onclick = showBvbQuizQuestion; // Re-assign click for next } function showBvbQuizResults() { bvbQuizActiveScreen.style.display = 'none'; bvbQuizResultsScreen.style.display = 'block'; bvbQuizResultsSummary.textContent = `You scored ${bvbQuizState.score} out of ${bvbQuizState.questions.length}!`; } // --- 6. PDF DOWNLOAD FUNCTION (Spec C, 9) --- async function downloadBvbPdf() { if (typeof jspdf === 'undefined' || typeof html2canvas === 'undefined') { alert('PDF libraries are still loading. Please try again in a moment.'); return; } const { jsPDF } = jspdf; const dashboardContent = bvbContainer.querySelector('#bvb-dashboard-content'); // Add print-friendly class bvbContainer.classList.add('bvb-pdf-view'); bvbPdfDownloadBtn.style.display = 'none'; try { const canvas = await html2canvas(dashboardContent, { scale: 2, useCORS: true, logging: false }); const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF('p', 'mm', 'a4'); const pdfWidth = pdf.internal.pageSize.getWidth(); const margin = 15; const contentWidth = pdfWidth - (margin * 2); const contentHeight = (canvas.height * contentWidth) / canvas.width; pdf.setFont("helvetica", "bold"); pdf.setFontSize(18); pdf.setTextColor(getComputedStyle(document.documentElement).getPropertyValue('--bvb-primary-color').trim()); pdf.text("My Vocabulary Word List", margin, margin + 5); pdf.addImage(imgData, 'PNG', margin, margin + 15, contentWidth, contentHeight); pdf.save('Vocabulary_Word_List.pdf'); } catch (error) { console.error("BVB PDF Error:", error); alert("An error occurred while generating the PDF."); } finally { // Clean up bvbContainer.classList.remove('bvb-pdf-view'); bvbPdfDownloadBtn.style.display = 'block'; } } // --- 7. UTILITY FUNCTIONS --- function escapeHTML(str) { if (typeof str !== 'string') return ''; return str.replace(/[&<>"']/g, m => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[m])); } // --- 8. EVENT BINDING (Spec IV.C) --- // Tab buttons bvbTabButtons.forEach((button, index) => { button.addEventListener('click', () => showBvbTab(index)); }); // Navigation buttons bvbNavNext.addEventListener('click', () => showBvbTab(currentBvbTab + 1)); bvbNavPrev.addEventListener('click', () => showBvbTab(currentBvbTab - 1)); // PDF Download bvbPdfDownloadBtn.addEventListener('click', downloadBvbPdf); // Config Tab bvbAddWordForm.addEventListener('submit', addBvbWord); bvbConfigWordList.addEventListener('click', (e) => { if (e.target.classList.contains('bvb-delete-word')) { const index = parseInt(e.target.dataset.index, 10); if (!isNaN(index)) { deleteBvbWord(index); } } }); // Flashcard Tab bvbFlashcardStartBtn.addEventListener('click', startBvbFlashcards); bvbFlashcardFlipBtn.addEventListener('click', flipBvbCard); bvbFlashcardNextBtn.addEventListener('click', nextBvbFlashcard); // Quiz Tab bvbQuizStartBtn.addEventListener('click', startBvbQuiz); bvbQuizRestartBtn.addEventListener('click', startBvbQuiz); // Note: Quiz submit button is handled in the quiz logic functions // --- 9. INITIALIZATION --- bvbWordList = [...bvbSampleData]; // Load sample data renderAllBvbContent(); // Populate all tabs showBvbTab(0); // Show the first tab });