<!DOCTYPE html>
<html lang="ar">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>منصة تعلم المفردات - Mr Mohamed Attia</title>
<link href="https://fonts.googleapis.com/css2?family=Cairo:wght@400;700;900&display=swap" rel="stylesheet">
<style>
/* --- Dark Mode Variables --- */
:root {
--background: #121212;
--surface: #1e1e1e;
--primary: #bb86fc;
--secondary: #ffc107;
--accent: #03dac6;
--danger: #cf6679;
--text: #ffffff;
--muted: #a0a0a0;
--border: #333333;
--radius: 1rem;
--shadow: 0 4px 12px rgba(0,0,0,0.5);
--ink: #ffffff;
}
body {
font-family: "Cairo", sans-serif;
background: var(--background);
color: var(--text);
margin: 0;
padding: 0;
line-height: 1.6;
direction: rtl;
}
header {
background: var(--surface);
box-shadow: var(--shadow);
padding: 1.5rem;
text-align: center;
}
.glow-title {
font-size: 26px;
font-weight: 900;
color: var(--ink);
text-align: center;
line-height: 1.4;
opacity: 0;
transform: translateY(-30px);
animation: fadeSlideIn 1.8s ease forwards;
}
/* --- التعديلات الجديدة: لون ظاهر وحركة دون توهج (Glow) --- */
.glow-title .highlight {
font-size: 30px;
background: linear-gradient(90deg, #bb86fc, #ffeb3b, #03dac6, #bb86fc);
background-size: 400%;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
display: inline-block;
animation: glow-move 6s linear infinite, pulse 2s ease-in-out infinite;
font-weight: 900;
filter: brightness(1.2);
}
@keyframes glow-move {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.08); }
}
@keyframes fadeSlideIn {
0% { opacity: 0; transform: translateY(-30px); }
100% { opacity: 1; transform: translateY(0); }
}
/* --- نهاية تعديلات الـ Highlight --- */
main {
padding: 2rem;
max-width: 1000px;
margin: auto;
}
.card {
background: var(--surface);
border-radius: var(--radius);
box-shadow: var(--shadow);
padding: 1.5rem;
margin-bottom: 1.5rem;
}
.card h2 {
margin-top: 0;
font-size: 22px;
color: var(--primary);
text-align: center;
border-bottom: 2px solid var(--primary);
padding-bottom: 0.5rem;
margin-bottom: 1.5rem;
}
/* --- NEW SEARCH BAR STYLE --- */
.search-container {
display: flex;
gap: 0.5rem;
align-items: center;
background: #2e2e2e;
padding: 0.5rem 1rem;
border-radius: var(--radius);
margin-bottom: 1rem;
}
.search-container label {
color: var(--secondary);
font-weight: 700;
}
.search-input {
flex-grow: 1;
padding: 0.6rem;
border: 1px solid var(--border);
border-radius: 8px;
background: #3a3a3a;
color: var(--text);
font-size: 1rem;
transition: border-color 0.3s;
text-align: right;
}
.search-input:focus {
border-color: var(--primary);
outline: none;
}
/* --- END SEARCH BAR STYLE --- */
/* Control Panel */
.control-panel {
display: flex;
flex-wrap: wrap;
gap: 1rem;
justify-content: space-between;
align-items: center;
margin-bottom: 1.5rem;
}
.control-panel .button-group {
display: flex;
gap: 1rem;
}
.start-button, .test-button {
background: var(--primary);
color: var(--text);
border: none;
padding: 0.7rem 1.2rem;
border-radius: var(--radius);
cursor: pointer;
font-size: 16px;
transition: 0.3s;
flex-grow: 1;
}
.start-button:hover, .test-button:hover {
background: #9d5ae8;
}
.test-button {
background: var(--secondary);
}
.test-button:hover {
background: #e6a800;
}
/* Speed Control Styles */
.speed-control {
display: flex;
align-items: center;
gap: 0.5rem;
color: var(--muted);
background: #2e2e2e;
padding: 0.5rem 1rem;
border-radius: var(--radius);
}
.speed-control input[type="range"] {
-webkit-appearance: none;
appearance: none;
width: 120px;
height: 8px;
background: var(--border);
outline: none;
opacity: 0.7;
transition: opacity 0.2s;
border-radius: 4px;
cursor: pointer;
}
.speed-control input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 18px;
height: 18px;
border-radius: 50%;
background: var(--accent);
cursor: pointer;
}
/* --- Vocabulary Table Styles (List Mode) --- */
.vocabulary-list {
display: flex;
flex-direction: column;
gap: 1rem;
}
.vocabulary-list h3 {
font-size: 1.15rem;
color: var(--secondary);
border-bottom: 1px dashed var(--border);
padding-bottom: 0.4rem;
margin-bottom: 0.8rem;
}
.vocabulary-group {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.2rem 1rem;
text-align: right;
}
.word-pair {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.2rem 0;
border-bottom: 1px dotted var(--border);
font-size: 0.95rem;
}
.word-pair:nth-child(even) {
background-color: #242424;
}
.english-word-container {
font-family: Arial, sans-serif;
font-weight: 700;
color: var(--ink);
text-align: left;
flex-grow: 1;
padding-right: 0.5rem;
cursor: pointer;
transition: color 0.2s ease-in-out; /* Added transition */
}
/* NEW: Click Effect Class */
.english-word-container.speaking {
color: var(--accent); /* Highlight on click/speak */
transform: scale(1.05);
}
.english-word-container:hover {
color: var(--primary);
}
.arabic-translation {
color: var(--text);
text-align: right;
padding-left: 0.5rem;
font-size: 0.9rem;
}
/* --- Quiz Styles --- */
#quiz-container {
padding: 2rem;
text-align: center;
min-height: 400px;
display: none;
flex-direction: column;
justify-content: center;
}
#question-text {
font-size: 1.8rem;
color: var(--accent);
margin-bottom: 2rem;
}
.options-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
margin-top: 1.5rem;
}
.option-button {
background: var(--surface);
color: var(--text);
border: 2px solid var(--border);
padding: 1rem;
border-radius: var(--radius);
cursor: pointer;
font-size: 1.1rem;
transition: 0.3s;
}
.option-button:hover {
border-color: var(--primary);
}
/* Feedback Colors */
.option-button.correct {
background: var(--accent);
color: #121212;
border-color: var(--accent);
font-weight: 700;
}
.option-button.wrong {
background: var(--danger);
color: var(--text);
border-color: var(--danger);
font-weight: 700;
}
.option-button:disabled {
opacity: 0.6;
cursor: not-allowed;
}
#result-message {
margin-top: 1.5rem;
font-size: 1.2rem;
color: var(--secondary);
}
/* --- FOOTER STYLES --- */
footer {
max-width: 1000px;
margin: 2rem auto 1rem;
padding: 1rem;
border-top: 1px solid var(--border);
text-align: center;
font-size: 0.9rem;
color: var(--muted);
}
footer p {
margin: 0.5rem 0;
}
footer .signature {
color: var(--primary);
font-weight: 700;
font-size: 1.1rem;
margin-bottom: 0.5rem;
}
footer .contact-info {
color: var(--accent);
font-family: Arial, sans-serif;
direction: ltr; /* Ensure the number is read LTR */
display: block;
font-size: 1rem;
}
/* Small Screen Adjustments */
@media (max-width: 768px) {
.control-panel {
flex-direction: column;
gap: 1.5rem;
}
.control-panel .button-group {
width: 100%;
}
.speed-control {
width: 100%;
justify-content: center;
}
.vocabulary-group {
grid-template-columns: 1fr;
}
.english-word-container {
padding-right: 0;
text-align: right;
font-size: 0.95rem;
}
.arabic-translation {
padding-left: 0;
font-size: 0.9rem;
}
.options-grid {
grid-template-columns: 1fr;
}
.search-container {
flex-direction: column;
}
.search-input {
width: 100%;
}
}
</style>
</head>
<body>
<header>
<h1 id="pageTitle" class="glow-title">
منصة تعلم المفردات - <span class="highlight">Mr Mohamed Attia</span>
</h1>
</header>
<main>
<div class="card">
<h2>مرحباً بك 👋</h2>
<p>اضغط على الكلمة الإنجليزية في الجدول لسماع النطق. استخدم زر الاختبار لبدء التمرين.</p>
<div class="control-panel">
<div class="button-group">
<button class="start-button" onclick="showVocabulary()">جدول المفردات</button>
<button class="test-button" onclick="startQuiz()">اختبار معاني الكلمات</button>
</div>
<div class="speed-control">
<label for="speechRate">سرعة الصوت:</label>
<input type="range" id="speechRate" min="0.5" max="2" value="1.0" step="0.1" onchange="updateRateDisplay(this.value)">
<span id="rateDisplay">1.0x</span>
</div>
</div>
</div>
<div id="vocabulary-viewer" class="card vocabulary-list">
<h2>جدول المفردات (Vocabulary Viewer)</h2>
<div class="search-container">
<label for="vocabularySearch">ابحث:</label>
<input type="text" id="vocabularySearch" class="search-input" placeholder="اكتب كلمة إنجليزية أو عربية..." onkeyup="filterVocabulary()">
</div>
<div class="vocabulary-section">
<h3>المفردات الأساسية والإضافية (جميع الكلمات)</h3>
<div class="vocabulary-group" id="all-vocabulary">
</div>
</div>
</div>
<div id="quiz-container" class="card">
<h2>اختبار معاني الكلمات</h2>
<p id="quiz-score">النتيجة: 0 / 0</p>
<p id="question-text"></p>
<div class="options-grid" id="options-grid">
</div>
<p id="result-message"></p>
<button class="start-button" id="next-button" style="display:none; margin-top: 1.5rem;" onclick="loadNewQuestion()">السؤال التالي</button>
</div>
</main>
<footer>
<p>تم تصميم هذا الموقع بواسطة <span class="signature">مستر محمد عطيه</span></p>
<p class="signature" style="margin-top: 10px;">Best of luck - Mr Mohamed Attia</p>
<span class="contact-info">01011999500</span>
</footer>
<script>
// --- 1. DATA (Contains ALL 98 words from both images) ---
const vocabularyData = [
// --- 1. Key Vocabulary ---
{ en: "achieve(d) (v)", ar: "يحقق - ينجز" },
{ en: "achievement (n)", ar: "إنجاز - نجاح" },
{ en: "admiration (n)", ar: "إعجاب" },
{ en: "admire(d) (v)", ar: "يُعجب - يحترم" },
{ en: "advance(d) (v)", ar: "يُقدم - يتقدم" },
{ en: "civilization (n)", ar: "حضارة" },
{ en: "heritage (n)", ar: "تراث" },
{ en: "pride (n)", ar: "فخر" },
{ en: "inherit(ed) (v)", ar: "يرث" },
{ en: "leading (adj)", ar: "بارز - هام" },
{ en: "merchant (n)", ar: "تاجر" },
{ en: "monuments (n)", ar: "آثار" },
{ en: "responsibility (n)", ar: "مسؤولية" },
{ en: "root (n)", ar: "جذر - أصل" },
{ en: "valuable (adj)", ar: "قيّم - نفيس" },
{ en: "value (n)", ar: "قيمة - ثمن" },
// --- 2. Important Vocabulary ---
{ en: "advice (n)", ar: "نصيحة" },
{ en: "article (n)", ar: "مقال" },
{ en: "amaze (d) (v)", ar: "يدهش - يذهل" },
{ en: "author (n)", ar: "مؤلف" },
{ en: "background (n)", ar: "خلفية" },
{ en: "benefit (n)", ar: "فائدة - منفعة" },
{ en: "challenge (n)", ar: "تحد - صعوبة" },
{ en: "communication (n)", ar: "تواصل" },
{ en: "conclusion (n)", ar: "خلاصة - استنتاج" },
{ en: "context (n)", ar: "سياق - إطار" },
{ en: "convenient (adj)", ar: "مناسب - مُلائم" },
{ en: "create(d) (v)", ar: "يُبدع - يُنشئ" },
{ en: "creative (adj)", ar: "إبداعي - ابتلاعي" },
{ en: "determination (n)", ar: "عزم - تصميم" },
{ en: "display(ed) (v)", ar: "يعرض - يُظهر" },
{ en: "elsewhere (adv)", ar: "في مكان آخر" },
{ en: "entire (adj)", ar: "كامل - كلي" },
{ en: "evidence (n)", ar: "دليل - برهان" },
{ en: "express(ed) (v)", ar: "يُعبر - يُفصح عن" },
{ en: "figure (n)", ar: "شخصية - رقم" },
{ en: "gift (n)", ar: "هدية - عطية" },
{ en: "habit (n)", ar: "عادة" },
{ en: "hook (n)", ar: "خُطّاف - فكرة مشوقة" },
{ en: "imagine (d) (v)", ar: "يتخيل" },
{ en: "impressive (adj)", ar: "مثير للإعجاب - مؤثر" },
{ en: "improve(d) (v)", ar: "يُحسن - يتحسن" },
{ en: "insight (n)", ar: "فهم واضح - تبصيرة" },
{ en: "knowledge (n)", ar: "معرفة - علم" },
{ en: "magnificent (adj)", ar: "مُذهل - رائع" },
{ en: "mighty (adj)", ar: "عظيم - قوي" },
{ en: "non-fiction (adj)", ar: "غير خيالي" },
{ en: "phrase (n)", ar: "عبارة - لُغز" },
{ en: "pleasure (n)", ar: "متعة - سرور" },
{ en: "point (n)", ar: "نقطة - موضوع" },
{ en: "poet (n)", ar: "شاعر" },
{ en: "regular (adj)", ar: "مُعتاد - تقليدي" },
{ en: "relax(ed) (v)", ar: "يسترخي - يهدأ" },
{ en: "rephrase(d) (v)", ar: "يعيد صياغة" },
{ en: "respect (n)", ar: "احترام - تقدير" },
{ en: "run-on (n)", ar: "جملة طويلة غير مفهومة" },
{ en: "scene (n)", ar: "مشهد" },
{ en: "shared (adj)", ar: "مشترك" },
{ en: "single (adj)", ar: "وحيد - مُفرد" },
{ en: "statement (n)", ar: "بيان - تصريح" },
{ en: "thesis (n)", ar: "أطروحة - طرح رئيسي" },
{ en: "thinker (n)", ar: "مفكر" },
{ en: "thinking (n)", ar: "تفكير" },
{ en: "tradition (n)", ar: "تقاليد - عرف" },
{ en: "treasures (n)", ar: "كنوز" },
{ en: "visualize(d) (v)", ar: "يتصور - يتخيل" },
{ en: "vision (n)", ar: "رؤية" },
{ en: "wisdom (n)", ar: "حكمة" },
{ en: "wise (adj)", ar: "حكيم" }
];
// --- 2. TTS & RATE CONTROL ---
const synth = window.speechSynthesis;
let currentRate = 1.0;
// Audio elements for quiz feedback (using external URLs as a fallback)
const correctAudio = new Audio('https://assets.mixkit.co/sfx/download/mixkit-correct-answer-in-a-video-game-2007.wav');
const wrongAudio = new Audio('https://assets.mixkit.co/sfx/download/mixkit-game-over-trombone-692.wav');
function speakWelcome() {
const welcomeMessage = "Welcome to Mr. Mohamed Attia's vocabulary website!";
const utterance = new SpeechSynthesisUtterance(welcomeMessage);
utterance.lang = 'en-US';
utterance.rate = 1.0;
utterance.volume = 1.0;
if (synth) {
synth.speak(utterance);
}
}
function updateRateDisplay(newRate) {
currentRate = parseFloat(newRate);
document.getElementById('rateDisplay').textContent = `${currentRate.toFixed(1)}x`;
if (synth.speaking) {
synth.cancel();
}
}
// UPDATED: speakWord function to ignore parentheses content
function speakWord(wordWithPOS) {
// --- التعديل هنا: استخدام تعبير نمطي لإزالة أي شيء داخل أقواس (بما في ذلك الأقواس نفسها) ---
// Example: "achieve(d) (v)" becomes "achieve"
// Example: "clutch (ed) (v)" becomes "clutch"
const wordToSpeak = wordWithPOS.replace(/\s*\(.*?\)/g, '').trim();
if (synth.speaking) {
synth.cancel();
}
// Find the element to apply the visual effect (using the full string as data attribute)
const element = document.querySelector(`.english-word-container[data-word='${wordWithPOS.replace(/'/g, "\\'")}']`);
if (element) {
element.classList.add('speaking'); // Apply highlight effect
}
const utterance = new SpeechSynthesisUtterance(wordToSpeak);
utterance.lang = 'en-US';
utterance.rate = currentRate;
utterance.volume = 1.0;
// Remove the visual effect after speaking is done
utterance.onend = () => {
if (element) {
element.classList.remove('speaking');
}
};
synth.speak(utterance);
}
// --- 3. VOCABULARY DISPLAY & FILTER ---
let allVocabElements = [];
function createVocabularyList(data, containerId, elementArray) {
const container = document.getElementById(containerId);
container.innerHTML = '';
elementArray.length = 0;
data.forEach(item => {
const wordPair = document.createElement('div');
wordPair.className = 'word-pair';
const englishContainer = document.createElement('span');
englishContainer.className = 'english-word-container';
// Use the full word (including POS) for data attribute to ensure uniqueness
englishContainer.setAttribute('data-word', item.en);
englishContainer.onclick = () => speakWord(item.en);
const englishTextSpan = document.createElement('span');
englishTextSpan.className = 'word-text';
englishTextSpan.textContent = item.en;
englishContainer.appendChild(englishTextSpan);
const arabicTextSpan = document.createElement('span');
arabicTextSpan.className = 'arabic-translation';
arabicTextSpan.textContent = item.ar;
wordPair.appendChild(englishContainer);
wordPair.appendChild(arabicTextSpan);
container.appendChild(wordPair);
// Store the actual DOM element for filtering
elementArray.push({ element: wordPair, en: item.en.toLowerCase(), ar: item.ar.toLowerCase() });
});
}
function filterVocabulary() {
const searchTerm = document.getElementById('vocabularySearch').value.toLowerCase().trim();
let foundCount = 0;
allVocabElements.forEach(item => {
const isMatch = item.en.includes(searchTerm) || item.ar.includes(searchTerm);
item.element.style.display = isMatch ? 'flex' : 'none';
if (isMatch) {
foundCount++;
}
});
const section = document.getElementById('all-vocabulary').closest('.vocabulary-section');
if (section) {
section.style.display = 'block';
}
}
// --- 4. QUIZ LOGIC ---
let currentQuestionIndex = 0;
let score = 0;
let totalQuestions = 0;
let quizWords = [];
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
function startQuiz() {
if (vocabularyData.length < 4) {
alert("تحتاج إلى 4 كلمات على الأقل لبدء الاختبار.");
return;
}
// Hide viewer and show quiz
document.getElementById('vocabulary-viewer').style.display = 'none';
document.getElementById('quiz-container').style.display = 'flex';
// Reset quiz state
score = 0;
totalQuestions = 0;
currentQuestionIndex = 0;
// Shuffle all words for the quiz order
quizWords = [...vocabularyData];
shuffleArray(quizWords);
updateScoreDisplay();
loadNewQuestion();
}
function loadNewQuestion() {
if (currentQuestionIndex >= quizWords.length) {
// Quiz finished
document.getElementById('question-text').textContent = "انتهى الاختبار!";
document.getElementById('result-message').innerHTML = `لقد أجبت على ${score} سؤالًا صحيحًا من أصل ${totalQuestions}. أحسنت!`;
document.getElementById('options-grid').innerHTML = '';
document.getElementById('next-button').style.display = 'none';
return;
}
const currentWord = quizWords[currentQuestionIndex];
const correctTranslation = currentWord.ar;
// Clean up the English word for display (removes the part of speech in brackets)
const englishWord = currentWord.en.replace(/\s+\(.*\)/g, '').trim();
// --- Prepare Question Text ---
// Allow clicking the word in the question to hear pronunciation
document.getElementById('question-text').innerHTML = `ما معنى كلمة: <span style="color: var(--primary); font-size: 1.2em; cursor:pointer;" onclick="speakWord('${currentWord.en}')">${englishWord}</span> ؟`;
document.getElementById('result-message').textContent = '';
document.getElementById('next-button').style.display = 'none';
// --- Select Wrong Options ---
const wrongOptions = vocabularyData
.filter(item => item.ar !== correctTranslation)
.map(item => item.ar);
shuffleArray(wrongOptions);
// Select 3 wrong options (or fewer if total words are less than 4)
const options = [correctTranslation, ...wrongOptions.slice(0, 3)].filter(Boolean);
shuffleArray(options); // Shuffle all 4 options
// --- Render Options ---
const optionsGrid = document.getElementById('options-grid');
optionsGrid.innerHTML = ''; // Clear previous options
options.forEach(option => {
const button = document.createElement('button');
button.className = 'option-button';
button.textContent = option;
button.setAttribute('data-answer', option);
button.onclick = () => checkAnswer(button, correctTranslation);
optionsGrid.appendChild(button);
});
}
function checkAnswer(selectedButton, correctTranslation) {
const allButtons = document.querySelectorAll('.option-button');
// Disable all buttons after one click
allButtons.forEach(btn => btn.disabled = true);
const selectedAnswer = selectedButton.getAttribute('data-answer');
totalQuestions++;
if (selectedAnswer === correctTranslation) {
score++;
selectedButton.classList.add('correct');
document.getElementById('result-message').textContent = 'إجابة صحيحة! 🎉';
correctAudio.currentTime = 0; // Rewind to start
correctAudio.play(); // Play correct sound
} else {
selectedButton.classList.add('wrong');
// Highlight the correct answer
allButtons.forEach(btn => {
if (btn.getAttribute('data-answer') === correctTranslation) {
btn.classList.add('correct');
}
});
document.getElementById('result-message').textContent = `إجابة خاطئة. الإجابة الصحيحة هي: ${correctTranslation}`;
wrongAudio.currentTime = 0; // Rewind to start
wrongAudio.play(); // Play wrong sound
}
updateScoreDisplay();
document.getElementById('next-button').style.display = 'block';
currentQuestionIndex++;
}
function updateScoreDisplay() {
document.getElementById('quiz-score').textContent = `النتيجة: ${score} / ${totalQuestions}`;
}
function showVocabulary() {
document.getElementById('quiz-container').style.display = 'none';
document.getElementById('vocabulary-viewer').style.display = 'flex';
filterVocabulary();
}
// --- 5. INITIALIZATION ---
document.addEventListener('DOMContentLoaded', () => {
// Initialize TTS
synth.getVoices();
// Build the SINGLE list using ALL data
createVocabularyList(vocabularyData, 'all-vocabulary', allVocabElements);
// Ensure the vocabulary viewer is shown by default on load
showVocabulary();
// تشغيل صوت الترحيب
setTimeout(speakWelcome, 500);
});
</script>
</body>
</html>
تعليقات
إرسال تعليق