Skip to content

Commit 7d7f64a

Browse files
Merge pull request #130 from chandra-011220/bug
removed caret from outside textboxarea and placed caret inside textbo…
2 parents b2dbab5 + 84d4783 commit 7d7f64a

3 files changed

Lines changed: 162 additions & 393 deletions

File tree

projects/typing-test/index.html

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!doctype html>
1+
<!doctype html>
22
<html lang="en">
33
<head>
44
<meta charset="utf-8">
@@ -17,12 +17,13 @@ <h1>Typing Test</h1>
1717
<option value="60" selected>60s</option>
1818
<option value="120">120s</option>
1919
</select>
20-
<button id="restartBtn">Restart</button>
20+
<button type="button" id="restartBtn">Restart</button>
2121
</div>
2222

23-
<div id="text" class="text" aria-live="polite"></div>
24-
<div id="caret" class="caret"></div>
25-
<div id="caret" class="caret"></div>
23+
<div class="text-container">
24+
<div id="text" class="text" aria-live="polite"></div>
25+
<div id="caret" class="caret"></div>
26+
</div>
2627

2728
<div class="stats">
2829
WPM: <span id="wpm">0</span> • Accuracy: <span id="acc">100</span>% • Time: <span id="time">60</span>s

projects/typing-test/main.js

Lines changed: 39 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,11 @@ function saveScore(wpm, accuracy) {
5959
username: generateAnonymousUsername()
6060
};
6161
userScores.push(score);
62-
if (userScores.length > 100) userScores = userScores.slice(-100);
62+
63+
if (userScores.length > 100) {
64+
userScores = userScores.slice(-100);
65+
}
66+
6367
localStorage.setItem('typingTestScores', JSON.stringify(userScores));
6468
return score;
6569
}
@@ -91,6 +95,7 @@ function displayLeaderboard(timeframe = 'daily') {
9195
leaderboardLoading.style.display = 'block';
9296
leaderboardEmpty.style.display = 'none';
9397
leaderboardList.innerHTML = '';
98+
9499
setTimeout(() => {
95100
const scores = getScoresByTimeframe(timeframe)
96101
.sort((a, b) => b.wpm - a.wpm || b.accuracy - a.accuracy)
@@ -166,6 +171,7 @@ function appendWords(count = 10) {
166171
}, 10);
167172
}
168173

174+
// FIXED: Update caret position
169175
function updateCaret() {
170176
const spans = textEl.querySelectorAll("span");
171177

@@ -178,23 +184,27 @@ function updateCaret() {
178184
}
179185

180186
const span = spans[index];
181-
182-
// Use requestAnimationFrame for better performance and timing
183-
requestAnimationFrame(() => {
184-
// Get the position relative to the text container
185-
const textRect = textEl.getBoundingClientRect();
186-
const spanRect = span.getBoundingClientRect();
187-
188-
// Position the caret at the beginning of the current character
189-
caret.style.left = `${spanRect.left - textRect.left}px`;
190-
caret.style.top = `${spanRect.top - textRect.top}px`;
191-
caret.style.height = `${spanRect.height}px`;
192-
caret.style.display = "block";
193-
caret.style.opacity = "1";
194-
195-
// mark current span for styling
196-
span.classList.add("current");
197-
});
187+
const textStyles = window.getComputedStyle(textEl);
188+
const paddingLeft = parseFloat(textStyles.paddingLeft);
189+
const paddingTop = parseFloat(textStyles.paddingTop);
190+
191+
// Calculate position relative to the text element's content area
192+
let left = paddingLeft;
193+
let top = paddingTop;
194+
195+
for (let i = 0; i < index; i++) {
196+
const s = spans[i];
197+
if (s.offsetTop === span.offsetTop) {
198+
left += s.offsetWidth;
199+
}
200+
}
201+
202+
top = span.offsetTop - spans[0].offsetTop + paddingTop;
203+
204+
caret.style.left = `${left}px`;
205+
caret.style.top = `${top}px`;
206+
caret.style.height = `${span.offsetHeight}px`;
207+
caret.style.display = "block";
198208
}
199209

200210
function startTimer() {
@@ -212,9 +222,11 @@ function startTimer() {
212222
function endTest() {
213223
document.removeEventListener("keydown", handleTyping);
214224
caret.style.display = "none";
225+
215226
const minutes = (Date.now() - start) / 60000;
216227
const wpm = Math.round((index / 5) / Math.max(minutes, 0.001));
217228
const acc = Math.round((correct / Math.max(index, 1)) * 100);
229+
218230
const savedScore = saveScore(wpm, acc);
219231
const highScore = isHighScore(wpm, currentTimeframe);
220232
showCurrentScore(wpm, acc, highScore);
@@ -236,12 +248,10 @@ function resetTest() {
236248
textArray = [];
237249
textEl.innerHTML = "";
238250
appendWords(30);
239-
240-
// Force caret to be visible and positioned
241-
forceCaretVisible();
242-
setTimeout(forceCaretVisible, 10);
243-
setTimeout(forceCaretVisible, 50);
244-
setTimeout(forceCaretVisible, 100);
251+
252+
setTimeout(() => {
253+
updateCaret();
254+
}, 10);
245255

246256
typedText = "";
247257
updateTitle(); // Reset title
@@ -301,6 +311,7 @@ function handleTyping(e) {
301311

302312
function initLeaderboard() {
303313
displayLeaderboard(currentTimeframe);
314+
304315
timeframeBtns.forEach(btn => {
305316
btn.addEventListener('click', () => {
306317
timeframeBtns.forEach(b => b.classList.remove('active'));
@@ -318,38 +329,12 @@ function checkScrollable() {
318329
}
319330

320331
window.addEventListener('load', checkScrollable);
321-
window.addEventListener('resize', checkScrollable);
322-
setTimeout(checkScrollable, 1000);
323-
324-
// Force caret to be visible
325-
function forceCaretVisible() {
326-
if (caret) {
327-
caret.style.display = "block";
328-
caret.style.opacity = "1";
329-
caret.style.visibility = "visible";
330-
updateCaret();
331-
}
332-
}
332+
window.addEventListener('resize', () => {
333+
checkScrollable();
334+
updateCaret();
335+
});
333336

334-
// Initialize
335337
resetTest();
336338
initLeaderboard();
337339
restartBtn.addEventListener("click", resetTest);
338340
timeSelect.addEventListener("change", resetTest);
339-
window.addEventListener("resize", updateCaret);
340-
341-
// Ensure caret is visible when page loads
342-
document.addEventListener("DOMContentLoaded", () => {
343-
setTimeout(forceCaretVisible, 100);
344-
setTimeout(forceCaretVisible, 300);
345-
setTimeout(forceCaretVisible, 500);
346-
});
347-
348-
// Also ensure caret is visible after a short delay
349-
setTimeout(forceCaretVisible, 200);
350-
setTimeout(forceCaretVisible, 400);
351-
setTimeout(forceCaretVisible, 800);
352-
353-
// Ensure caret is visible when window gets focus
354-
window.addEventListener("focus", forceCaretVisible);
355-
window.addEventListener("load", forceCaretVisible);

0 commit comments

Comments
 (0)