Skip to content

Commit 7b7e9de

Browse files
committed
Add + and - for 0-20
1 parent d8723c5 commit 7b7e9de

6 files changed

Lines changed: 950 additions & 11 deletions
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Addition & Subtraction Flashcards (0-20)</title>
7+
<link rel="stylesheet" href="styles.css">
8+
</head>
9+
<body>
10+
<div class="main-content">
11+
<div class="problem-area">
12+
<div class="header-container">
13+
<a href="index.html" class="home-button">🏠 Home</a>
14+
<h1>⚡ Flashcards: Add & Subtract (0-20)</h1>
15+
<div class="orientation-toggle">
16+
<span class="toggle-label horizontal active">Horizontal</span>
17+
<label class="switch">
18+
<input type="checkbox" id="orientation-switch">
19+
</label>
20+
<span class="toggle-label vertical">Vertical</span>
21+
<div class="slider-bg"></div>
22+
</div>
23+
</div>
24+
<div class="container flashcard-page-container">
25+
<div class="flashcard-container" id="flashcard-container">
26+
<div class="flashcard" id="flashcard">
27+
<div class="flashcard-front" id="flashcard-front">
28+
<span id="problem-text">Loading...</span>
29+
</div>
30+
<div class="flashcard-back" id="flashcard-back">
31+
<span id="answer-text"></span>
32+
</div>
33+
</div>
34+
</div>
35+
<div class="flashcard-navigation">
36+
<button class="nav-button" id="flip-btn">Flip</button>
37+
<button class="nav-button" id="next-btn" style="display: none;">Next →</button>
38+
</div>
39+
</div>
40+
</div>
41+
<!-- No scratchpad area -->
42+
</div>
43+
<div class="problem-type">
44+
Addition & Subtraction (0-20) Flashcards
45+
</div>
46+
<!-- Stars container might not be relevant here, but kept for consistency -->
47+
<div class="stars" id="stars-container"></div>
48+
<!-- animations.js included for potential future use or consistency -->
49+
<script src="animations.js" type="module" defer></script>
50+
<script src="addition-subtraction-0-20-flashcards.js" type="module" defer></script>
51+
</body>
52+
</html>
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
// We can reuse the problem generation logic
2+
// No need for animationSystem here unless we add feedback animations
3+
4+
let currentProblem = null;
5+
let isVertical = false; // State for orientation
6+
7+
// DOM Elements
8+
const problemTextElement = document.getElementById('problem-text');
9+
const answerTextElement = document.getElementById('answer-text');
10+
const flashcardElement = document.getElementById('flashcard');
11+
const flashcardContainer = document.getElementById('flashcard-container'); // Need container for size change
12+
const flipButton = document.getElementById('flip-btn');
13+
const nextButton = document.getElementById('next-btn');
14+
const orientationSwitch = document.getElementById('orientation-switch');
15+
const horizontalLabel = document.querySelector('.toggle-label.horizontal');
16+
const verticalLabel = document.querySelector('.toggle-label.vertical');
17+
const sliderBg = document.querySelector('.slider-bg');
18+
19+
// --- Problem Generation (copied/adapted from addition-subtraction-0-20.js) ---
20+
function generateProblem(vertical = false) { // Accept orientation flag
21+
const isAddition = Math.random() < 0.5;
22+
let num1, num2, correctAnswer, questionText;
23+
const maxVal = 20;
24+
25+
let displayNum1, displayNum2; // Numbers specifically for display
26+
27+
if (isAddition) {
28+
correctAnswer = Math.floor(Math.random() * (maxVal + 1)); // Result between 0 and 20
29+
num1 = Math.floor(Math.random() * (correctAnswer + 1)); // First number <= result
30+
num2 = correctAnswer - num1; // Second number ensures sum is correctAnswer
31+
32+
// Ensure larger number is first for display
33+
if (num2 > num1) {
34+
displayNum1 = num2;
35+
displayNum2 = num1;
36+
} else {
37+
displayNum1 = num1;
38+
displayNum2 = num2;
39+
}
40+
41+
if (vertical) {
42+
// Format for vertical display using HTML
43+
const num1Str = String(displayNum1).padStart(2, ' '); // Pad for alignment
44+
const num2Str = String(displayNum2).padStart(2, ' ');
45+
// Structure for better CSS control
46+
questionText = `<span class="num-line">&nbsp;&nbsp;${num1Str}</span>
47+
<span class="num-line op">+ ${num2Str}</span>
48+
<span class="op-line"></span>
49+
<span class="num-line q-mark">&nbsp;&nbsp;?</span>`;
50+
} else {
51+
questionText = `${displayNum1} + ${displayNum2} = ?`;
52+
}
53+
} else { // Subtraction
54+
num1 = Math.floor(Math.random() * (maxVal + 1)); // First number between 0 and 20
55+
num2 = Math.floor(Math.random() * (num1 + 1)); // Second number <= first number (ensures non-negative result)
56+
correctAnswer = num1 - num2;
57+
58+
// For subtraction, num1 is already >= num2, so use them directly
59+
displayNum1 = num1;
60+
displayNum2 = num2;
61+
62+
if (vertical) {
63+
// Format for vertical display using HTML
64+
const num1Str = String(displayNum1).padStart(2, ' '); // Pad for alignment
65+
const num2Str = String(displayNum2).padStart(2, ' ');
66+
// Structure for better CSS control
67+
questionText = `<span class="num-line">&nbsp;&nbsp;${num1Str}</span>
68+
<span class="num-line op">- ${num2Str}</span>
69+
<span class="op-line"></span>
70+
<span class="num-line q-mark">&nbsp;&nbsp;?</span>`;
71+
} else {
72+
questionText = `${displayNum1} - ${displayNum2} = ?`;
73+
}
74+
}
75+
76+
return {
77+
questionText: questionText, // Can be HTML string now
78+
correctAnswer: correctAnswer // Use the original calculated answer
79+
};
80+
}
81+
82+
// --- Flashcard Logic ---
83+
84+
// Loads new problem data and updates ONLY the front text
85+
function loadNewProblemData() {
86+
currentProblem = generateProblem(isVertical); // Pass current orientation
87+
if (isVertical) {
88+
problemTextElement.innerHTML = currentProblem.questionText; // Use innerHTML for vertical format
89+
flashcardElement.classList.add('vertical');
90+
flashcardContainer.classList.add('vertical');
91+
} else {
92+
problemTextElement.textContent = currentProblem.questionText; // Use textContent for horizontal
93+
flashcardElement.classList.remove('vertical');
94+
flashcardContainer.classList.remove('vertical');
95+
}
96+
// Answer is updated in flipCard
97+
}
98+
99+
// Handles flipping the card to show the answer
100+
function flipCard() {
101+
// Update the answer text JUST BEFORE flipping
102+
if (currentProblem) {
103+
answerTextElement.textContent = currentProblem.correctAnswer;
104+
answerTextElement.style.visibility = 'visible'; // Ensure it's visible
105+
}
106+
flashcardElement.classList.add('is-flipped');
107+
flipButton.style.display = 'none';
108+
nextButton.style.display = 'inline-block';
109+
}
110+
111+
// Handles going to the next card
112+
function displayNextProblem() {
113+
// Hide the answer content immediately
114+
answerTextElement.style.visibility = 'hidden';
115+
116+
// Start flip back animation
117+
flashcardElement.classList.remove('is-flipped');
118+
119+
// Wait for the flip back animation to start visually before changing front content
120+
setTimeout(() => {
121+
loadNewProblemData(); // Load and display new problem data on the FRONT only
122+
123+
// Reset button visibility
124+
flipButton.style.display = 'inline-block';
125+
nextButton.style.display = 'none';
126+
}, 100); // Shorter delay might be sufficient now
127+
}
128+
129+
// Handle orientation toggle - UPDATED for new design
130+
function handleOrientationChange() {
131+
isVertical = orientationSwitch.checked;
132+
133+
// Update the visual state of the toggle
134+
if (isVertical) {
135+
horizontalLabel.classList.remove('active');
136+
verticalLabel.classList.add('active');
137+
sliderBg.classList.add('vertical');
138+
} else {
139+
horizontalLabel.classList.add('active');
140+
verticalLabel.classList.remove('active');
141+
sliderBg.classList.remove('vertical');
142+
}
143+
144+
loadNewProblemData(); // Load a new problem in the new orientation
145+
146+
// Reset card state regardless
147+
flashcardElement.classList.remove('is-flipped');
148+
answerTextElement.style.visibility = 'hidden';
149+
flipButton.style.display = 'inline-block';
150+
nextButton.style.display = 'none';
151+
}
152+
153+
// --- Event Listeners ---
154+
// Add click events on the labels for better UX
155+
horizontalLabel.addEventListener('click', () => {
156+
if (orientationSwitch.checked) {
157+
orientationSwitch.checked = false;
158+
handleOrientationChange();
159+
}
160+
});
161+
162+
verticalLabel.addEventListener('click', () => {
163+
if (!orientationSwitch.checked) {
164+
orientationSwitch.checked = true;
165+
handleOrientationChange();
166+
}
167+
});
168+
169+
flipButton.addEventListener('click', flipCard);
170+
nextButton.addEventListener('click', displayNextProblem);
171+
orientationSwitch.addEventListener('change', handleOrientationChange);
172+
173+
// Add click listener to the flashcard itself
174+
flashcardElement.addEventListener('click', () => {
175+
if (flashcardElement.classList.contains('is-flipped')) {
176+
// If card is flipped (showing answer), clicking goes to next
177+
displayNextProblem();
178+
} else {
179+
// If card is not flipped (showing question), clicking flips it
180+
flipCard();
181+
}
182+
});
183+
184+
// Initial Load
185+
document.addEventListener('DOMContentLoaded', () => {
186+
isVertical = orientationSwitch.checked; // Check initial state
187+
// Update visual state to match initial checkbox state
188+
if (isVertical) {
189+
horizontalLabel.classList.remove('active');
190+
verticalLabel.classList.add('active');
191+
sliderBg.classList.add('vertical');
192+
}
193+
loadNewProblemData(); // Load the first problem's front data
194+
answerTextElement.style.visibility = 'hidden'; // Ensure answer starts hidden
195+
flipButton.style.display = 'inline-block';
196+
nextButton.style.display = 'none';
197+
});

addition-subtraction-0-20.html

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Addition & Subtraction (0-20)</title>
7+
<link rel="stylesheet" href="styles.css">
8+
</head>
9+
<body>
10+
<div class="main-content">
11+
<div class="problem-area">
12+
<div class="header-container">
13+
<a href="index.html" class="home-button">🏠 Home</a>
14+
<h1>🔢 Addition & Subtraction (0-20)</h1>
15+
<button class="toggle-scratchpad" id="toggle-scratchpad">📝 Open Scratchpad</button>
16+
</div>
17+
<div class="container">
18+
<div class="problem" id="problem-text">Loading problem...</div>
19+
<div class="options" id="options-container">
20+
<!-- Options dynamically loaded -->
21+
</div>
22+
<div class="navigation">
23+
<button class="nav-button" id="prev-problem">← Previous</button>
24+
<button class="nav-button" id="next-problem">Next →</button>
25+
</div>
26+
</div>
27+
</div>
28+
<div class="scratchpad-area" id="scratchpad-area">
29+
<div class="scratchpad-controls">
30+
<button class="scratchpad-button" id="undo-btn">↩️ Undo</button>
31+
<button class="scratchpad-button" id="redo-btn">↪️ Redo</button>
32+
<button class="scratchpad-button clear" id="clear-btn">🗑️ Clear</button>
33+
<button class="scratchpad-button" id="close-scratchpad">❌ Close</button>
34+
</div>
35+
<canvas class="scratchpad-canvas" id="scratchpad"></canvas>
36+
</div>
37+
</div>
38+
<div class="problem-type">
39+
Addition & Subtraction (0-20) Problems
40+
</div>
41+
<div class="stars" id="stars-container"></div>
42+
<script src="animations.js" type="module" defer></script>
43+
<script src="addition-subtraction-0-20.js" type="module" defer></script>
44+
</body>
45+
</html>

0 commit comments

Comments
 (0)