// Mobile menu toggle document.addEventListener('DOMContentLoaded', function() { const toggle = document.querySelector('.menu-toggle'); const navList = document.querySelector('.nav-list'); if (toggle) { toggle.addEventListener('click', function() { navList.classList.toggle('open'); }); } // Close menu on link click const navLinks = document.querySelectorAll('.nav-list a'); navLinks.forEach(function(link) { link.addEventListener('click', function() { if (navList) navList.classList.remove('open'); }); }); // Highlight active page in nav const currentPage = window.location.pathname.split('/').pop() || 'index.html'; navLinks.forEach(function(link) { const href = link.getAttribute('href'); if (href === currentPage) { link.classList.add('active'); } }); }); // --- Exercises --- function checkExercise(btn) { const exercise = btn.closest('.exercise'); const selected = exercise.querySelector('input[type="radio"]:checked'); const feedback = exercise.querySelector('.feedback'); if (!selected) { feedback.textContent = 'Please select an answer!'; feedback.className = 'feedback wrong'; feedback.style.display = 'block'; return; } const options = exercise.querySelectorAll('.option'); options.forEach(function(opt) { opt.classList.remove('correct', 'wrong'); }); const parent = selected.closest('.option'); const isCorrect = selected.value === 'true'; if (isCorrect) { parent.classList.add('correct'); feedback.textContent = 'Correct!'; feedback.className = 'feedback correct'; } else { parent.classList.add('wrong'); feedback.textContent = 'Try again!'; feedback.className = 'feedback wrong'; // Show correct answer options.forEach(function(opt) { const radio = opt.querySelector('input[type="radio"]'); if (radio && radio.value === 'true') { opt.classList.add('correct'); } }); } feedback.style.display = 'block'; } function checkFill(input) { const exercise = input.closest('.exercise'); const answer = input.getAttribute('data-answer'); const feedback = exercise.querySelector('.feedback'); input.classList.remove('correct', 'wrong'); if (input.value.trim().toLowerCase() === answer.toLowerCase()) { input.classList.add('correct'); feedback.textContent = 'Correct!'; feedback.className = 'feedback correct'; } else { input.classList.add('wrong'); feedback.textContent = 'Try again! Correct answer: ' + answer; feedback.className = 'feedback wrong'; } feedback.style.display = 'block'; } function checkTranslate(btn) { const exercise = btn.closest('.exercise'); const input = exercise.querySelector('input[type="text"]'); const feedback = exercise.querySelector('.feedback'); const answer = input.getAttribute('data-answer'); input.classList.remove('correct', 'wrong'); if (input.value.trim().toLowerCase() === answer.toLowerCase()) { input.classList.add('correct'); feedback.textContent = 'Correct!'; feedback.className = 'feedback correct'; } else { input.classList.add('wrong'); feedback.textContent = 'Try again! Correct answer: ' + answer; feedback.className = 'feedback wrong'; } feedback.style.display = 'block'; } function checkMatch(btn) { const exercise = btn.closest('.exercise'); const inputs = exercise.querySelectorAll('input[type="text"]'); const feedback = exercise.querySelector('.feedback'); let allCorrect = true; inputs.forEach(function(input) { const answer = input.getAttribute('data-answer'); input.classList.remove('correct', 'wrong'); if (input.value.trim().toLowerCase() === answer.toLowerCase()) { input.classList.add('correct'); } else { input.classList.add('wrong'); allCorrect = false; } }); if (allCorrect) { feedback.textContent = 'All correct! Great job!'; feedback.className = 'feedback correct'; } else { feedback.textContent = 'Some answers are wrong. Try again!'; feedback.className = 'feedback wrong'; } feedback.style.display = 'block'; } // --- Tests --- function checkTest() { let score = 0; const total = document.querySelectorAll('.test-question').length; const questions = document.querySelectorAll('.test-question'); questions.forEach(function(q) { const selected = q.querySelector('input[type="radio"]:checked'); if (selected && selected.value === 'true') { score++; } }); const resultBox = document.getElementById('test-result'); const scoreDisplay = document.getElementById('score'); scoreDisplay.textContent = score + '/' + total; resultBox.classList.add('show'); // Scroll to result resultBox.scrollIntoView({ behavior: 'smooth' }); } // --- Contact form --- function submitForm(event) { event.preventDefault(); const message = document.getElementById('form-message'); message.classList.add('show'); document.getElementById('contact-form').reset(); setTimeout(function() { message.classList.remove('show'); }, 5000); } // --- Pronunciation --- function speakWord(word, rate) { if (!window.speechSynthesis) { alert('Speech synthesis is not supported in your browser.'); return; } window.speechSynthesis.cancel(); var utterance = new SpeechSynthesisUtterance(word); utterance.lang = 'en-US'; utterance.rate = rate || 0.9; utterance.pitch = 1; window.speechSynthesis.speak(utterance); } function repeatWord(btn) { var word = btn.getAttribute('data-word'); speakWord(word, 0.8); btn.textContent = '🔊 Playing...'; setTimeout(function() { btn.textContent = '🔊 Listen'; }, 1500); } function speakSlow(btn) { var word = btn.getAttribute('data-word'); speakWord(word, 0.4); btn.textContent = '🐢 Slow...'; setTimeout(function() { btn.innerHTML = '🐢 Slow'; }, 2000); } function checkDictation(input) { var exercise = input.closest('.exercise'); var answer = input.getAttribute('data-answer'); var feedback = exercise.querySelector('.feedback'); input.classList.remove('correct', 'wrong'); if (input.value.trim().toLowerCase() === answer.toLowerCase()) { input.classList.add('correct'); feedback.textContent = 'Correct! Great listening!'; feedback.className = 'feedback correct'; } else { input.classList.add('wrong'); feedback.textContent = 'Not quite. The correct word is: ' + answer; feedback.className = 'feedback wrong'; } feedback.style.display = 'block'; } function speakPhrase(btn) { var phrase = btn.getAttribute('data-phrase'); speakWord(phrase, 0.8); btn.textContent = '🔊 Playing...'; setTimeout(function() { btn.innerHTML = '🔊 Hear Phrase'; }, 1500); } // --- Daily Reminder at 20:00 --- (function() { var LS_KEY = 'english_easy_daily'; var TOAST_SHOWN = false; function getToday() { return new Date().toDateString(); } function getStreak() { var data = JSON.parse(localStorage.getItem(LS_KEY) || '{"streak":0,"lastDate":""}'); var yesterday = new Date(); yesterday.setDate(yesterday.getDate() - 1); var yesterdayStr = yesterday.toDateString(); var today = getToday(); if (data.lastDate === today) { // already done today } else if (data.lastDate === yesterdayStr) { // consecutive day } else if (data.lastDate && data.lastDate !== today) { data.streak = 0; } return data; } function saveStreak(data) { data.lastDate = getToday(); localStorage.setItem(LS_KEY, JSON.stringify(data)); } function showDailyToast() { if (TOAST_SHOWN) return; TOAST_SHOWN = true; var data = getStreak(); var existing = document.querySelector('.daily-toast'); if (existing) existing.remove(); var toast = document.createElement('div'); toast.className = 'daily-toast'; var streakHTML = ''; if (data.streak > 0) { streakHTML = '
🔥 Day ' + data.streak + ' streak!
'; } toast.innerHTML = '
' + '
⏰ Daily Practice
' + '' + '
' + streakHTML + '

It\'s time for your daily English practice! Spend 5 minutes on an exercise or test.

' + '
' + 'Practice Now' + '' + '
'; document.body.appendChild(toast); // trigger animation setTimeout(function() { toast.classList.add('show'); }, 100); // also try browser notification if ('Notification' in window && Notification.permission === 'granted') { new Notification('English Easy — Daily Practice', { body: 'Time for your daily English practice! 5 minutes is all you need.', icon: '/images/icon.png' }); } } // Expose saveStreak for the toast button window.saveStreakFunc = function() { var data = getStreak(); data.streak = (data.streak || 0) + 1; saveStreak(data); }; // Request notification permission function requestNotifPermission() { if ('Notification' in window && Notification.permission === 'default') { Notification.requestPermission(); } } function checkDailyReminder() { var now = new Date(); var hours = now.getHours(); var minutes = now.getMinutes(); var data = getStreak(); // Show if it's >= 20:00 and we haven't shown today if (hours >= 20 && data.lastDate !== getToday()) { showDailyToast(); return true; } return false; } // Check on page load document.addEventListener('DOMContentLoaded', function() { requestNotifPermission(); checkDailyReminder(); // Check every 30 seconds if it's 20:00 setInterval(function() { var now = new Date(); if (now.getHours() === 20 && now.getMinutes() === 0) { checkDailyReminder(); } }, 30000); }); })(); // --- Vocabulary filter --- function filterVocab(category, btn) { const rows = document.querySelectorAll('.vocab-row'); const buttons = document.querySelectorAll('.category-btn'); buttons.forEach(function(b) { b.classList.remove('active'); }); if (btn) btn.classList.add('active'); rows.forEach(function(row) { if (category === 'all' || row.getAttribute('data-category') === category) { row.style.display = ''; } else { row.style.display = 'none'; } }); }