
Prompt
Please create a javascript-based typing test - it should show random words in sequence and measure typing speed to get through 100 words, and take keyboard input
A system prompt was added to support web rendering
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Simple Typing Test (100 Words)</title>
<style>
body{
font-family: Arial, Helvetica, sans-serif;
margin:40px;
line-height:1.5em;
background:#f5f7fa;
}
h1{margin-bottom:10px}
#wordContainer{
background:#fff;
padding:20px;
border:1px solid #ccc;
border-radius:6px;
min-height:120px;
font-size:22px;
user-select:none;
}
#wordContainer span{
margin-right:6px;
}
#wordContainer .current{
text-decoration:underline;
color:#1a73e8;
}
#wordContainer .correct{
color:#28a745;
}
#wordContainer .incorrect{
color:#dc3545;
}
#typeInput{
width:100%;
padding:12px;
font-size:20px;
margin-top:25px;
border:2px solid #1a73e8;
border-radius:4px;
box-sizing:border-box;
}
#stats{
margin-top:25px;
font-size:20px;
}
#startBtn,#resetBtn{
margin-top:20px;
padding:10px 18px;
background:#1a73e8;
color:#fff;
font-size:16px;
border:none;
border-radius:4px;
cursor:pointer;
}
#resetBtn{
display:none;
background:#6c757d;
}
</style>
</head>
<body>
<h1>Typing Test – 100 Random Words</h1>
<div id="wordContainer"></div>
<input id="typeInput" placeholder="Start typing here…" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" disabled>
<div id="stats"></div>
<button id="startBtn">Start Test</button>
<button id="resetBtn">Restart</button>
<script>
(function(){
// ================================================
// Configuration / Data
// ================================================
const WORD_COUNT = 100;
const WORD_BANK = [
"the","of","and","to","a","in","is","you","that","it","he","was","for","on","are",
"as","with","his","they","I","at","be","this","have","from","or","one","had","by",
"word","but","not","what","all","were","we","when","your","can","said","there","use",
"an","each","which","she","do","how","their","if","will","up","other","about","out",
"many","then","them","these","so","some","her","would","make","like","him","into",
"time","has","look","two","more","write","go","see","number","no","way","could",
"people","my","than","first","water","been","call","who","oil","its","now","find",
"long","down","day","did","get","come","made","may","part","new","sound"
];
// ================================================
// DOM references
// ================================================
const wordContainer = document.getElementById('wordContainer');
const input = document.getElementById('typeInput');
const statsDiv = document.getElementById('stats');
const startBtn = document.getElementById('startBtn');
const resetBtn = document.getElementById('resetBtn');
// ================================================
// State
// ================================================
let words = [];
let currentIndex = 0;
let started = false;
let startTime = 0;
let correctWords = 0;
let totalTypedWords = 0;
// ================================================
// Functions
// ================================================
function randomWord(){
return WORD_BANK[Math.floor(Math.random()*WORD_BANK.length)];
}
function generateWords(){
words = [];
for(let i=0;i<WORD_COUNT;i++){
words.push(randomWord());
}
}
function renderWords(){
wordContainer.innerHTML = words.map((w,i)=>`<span id="w${i}" class="${i===0?'current':''}">${w}</span>`).join(' ');
}
function resetTest(){
currentIndex = 0;
started = false;
startTime = 0;
correctWords = 0;
totalTypedWords = 0;
statsDiv.textContent = '';
input.value = '';
input.disabled = true;
startBtn.style.display = '';
resetBtn.style.display = 'none';
generateWords();
renderWords();
}
function startTest(){
input.disabled = false;
input.focus();
startBtn.style.display = 'none';
resetBtn.style.display = '';
}
function finishTest(){
const elapsedSec = (Date.now() - startTime) / 1000;
const wpm = (correctWords / elapsedSec) * 60;
const accuracy = (correctWords / totalTypedWords) * 100 || 0;
statsDiv.innerHTML = `
<strong>Completed!</strong><br>
Time: ${elapsedSec.toFixed(1)} s<br>
Correct Words: ${correctWords}/${WORD_COUNT}<br>
Accuracy: ${accuracy.toFixed(1)}%<br>
WPM: ${wpm.toFixed(1)}
`;
input.disabled = true;
input.value = '';
}
function handleInput(e){
// Start timer on first key press
if(!started){
started = true;
startTime = Date.now();
}
// Detect space or enter
if(e.key === ' ' || e.key === 'Enter'){
e.preventDefault(); // prevent adding space to input
const typed = input.value.trim();
const currentWord = words[currentIndex];
const span = document.getElementById(`w${currentIndex}`);
if(typed.length>0){ // ignore consecutive spaces
if(typed === currentWord){
span.classList.add('correct');
correctWords++;
}else{
span.classList.add('incorrect');
}
span.classList.remove('current');
currentIndex++;
totalTypedWords++;
if(currentIndex < WORD_COUNT){
document.getElementById(`w${currentIndex}`).classList.add('current');
}
input.value = '';
if(currentIndex === WORD_COUNT){
finishTest();
}
}
}
}
// ================================================
// Event Listeners
// ================================================
input.addEventListener('keydown', handleInput);
startBtn.addEventListener('click', startTest);
resetBtn.addEventListener('click', resetTest);
// ================================================
// Init
// ================================================
resetTest(); // generate first set
})();
</script>
</body>
</html>
```Here is a self-contained, JavaScript-based typing test. Copy the code below into an HTML file and open it in your browser to begin.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Typing Speed Test</title>
<style>
:root {
--background-color: #2c3e50;
--text-color: #ecf0f1;
--main-color: #3498db;
--incorrect-color: #e74c3c;
--correct-color: #2ecc71;
--sub-color: #95a5a6;
--input-bg-color: #34495e;
}
body {
background-color: var(--background-color);
color: var(--text-color);
font-family: 'Roboto Mono', monospace;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
padding: 20px;
box-sizing: border-box;
}
.test-container {
width: 100%;
max-width: 800px;
text-align: center;
}
h1 {
color: var(--main-color);
font-size: 2.5rem;
margin-bottom: 1rem;
}
p.instructions {
color: var(--sub-color);
font-size: 1rem;
margin-bottom: 2rem;
}
#stats {
display: flex;
justify-content: center;
align-items: center;
gap: 2rem;
font-size: 1.5rem;
margin-bottom: 1.5rem;
color: var(--main-color);
}
#words-container {
background-color: var(--input-bg-color);
padding: 1.5rem;
border-radius: 8px;
font-size: 1.5rem;
margin-bottom: 1.5rem;
height: 140px;
overflow: hidden;
text-align: left;
line-height: 2.2;
position: relative;
}
.word {
margin: 0 5px;
padding: 2px 4px;
border-radius: 4px;
transition: color 0.15s, background-color 0.15s;
}
.word.current {
background-color: var(--main-color);
color: var(--background-color);
}
.word.correct {
color: var(--correct-color);
}
.word.incorrect {
color: var(--incorrect-color);
text-decoration: underline;
}
#typing-input {
width: 90%;
padding: 1rem;
font-size: 1.5rem;
border-radius: 8px;
border: 2px solid var(--main-color);
background-color: var(--input-bg-color);
color: var(--text-color);
font-family: inherit;
text-align: center;
}
#typing-input:focus {
outline: none;
border-color: var(--correct-color);
box-shadow: 0 0 10px var(--correct-color);
}
#restart-btn {
margin-top: 1.5rem;
padding: 1rem 2rem;
font-size: 1.2rem;
border-radius: 8px;
border: none;
background-color: var(--main-color);
color: var(--text-color);
cursor: pointer;
transition: background-color 0.2s;
}
#restart-btn:hover {
background-color: #2980b9;
}
#results {
margin-top: 2rem;
font-size: 1.2rem;
background-color: var(--input-bg-color);
padding: 2rem;
border-radius: 8px;
}
#results h2 {
color: var(--main-color);
margin-top: 0;
font-size: 2rem;
}
.result-item {
display: flex;
justify-content: space-between;
max-width: 300px;
margin: 1rem auto;
font-size: 1.2rem;
}
.result-item span:first-child {
color: var(--sub-color);
}
.result-item span:last-child {
color: var(--text-color);
font-weight: bold;
}
.hidden {
display: none;
}
</style>
</head>
<body>
<div class="test-container">
<h1>Typing Test</h1>
<p class="instructions">Type the words below. The test will begin on your first keystroke.</p>
<div id="game-area">
<div id="stats">
<div id="timer">Time: 0:00</div>
</div>
<div id="words-container"></div>
<input type="text" id="typing-input" autofocus autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" />
</div>
<div id="results" class="hidden">
<h2>Results</h2>
<div class="result-item">
<span>Words Per Minute (WPM)</span>
<span id="wpm">0</span>
</div>
<div class="result-item">
<span>Accuracy</span>
<span id="accuracy">0%</span>
</div>
<div class="result-item">
<span>Correct Words</span>
<span id="correct-words">0</span>
</div>
<div class="result-item">
<span>Incorrect Words</span>
<span id="incorrect-words">0</span>
</div>
</div>
<button id="restart-btn">Restart Test</button>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const wordList = [
'the', 'be', 'to', 'of', 'and', 'a', 'in', 'that', 'have', 'I',
'it', 'for', 'not', 'on', 'with', 'he', 'as', 'you', 'do', 'at',
'this', 'but', 'his', 'by', 'from', 'they', 'we', 'say', 'her', 'she',
'or', 'an', 'will', 'my', 'one', 'all', 'would', 'there', 'their', 'what',
'so', 'up', 'out', 'if', 'about', 'who', 'get', 'which', 'go', 'me',
'when', 'make', 'can', 'like', 'time', 'no', 'just', 'him', 'know', 'take',
'people', 'into', 'year', 'your', 'good', 'some', 'could', 'them', 'see', 'other',
'than', 'then', 'now', 'look', 'only', 'come', 'its', 'over', 'think', 'also',
'back', 'after', 'use', 'two', 'how', 'our', 'work', 'first', 'well', 'way',
'even', 'new', 'want', 'because', 'any', 'these', 'give', 'day', 'most', 'us',
'is', 'are', 'was', 'were', 'has', 'had', 'said', 'went', 'did', 'got',
'were', 'find', 'long', 'down', 'day', 'did', 'get', 'come', 'made', 'may',
'part', 'number', 'sound', 'no', 'most', 'people', 'my', 'over', 'know', 'water',
'than', 'call', 'first', 'who', 'may', 'down', 'side', 'been', 'now', 'find',
'head', 'stand', 'own', 'page', 'should', 'country', 'found', 'answer', 'school', 'grow',
'study', 'still', 'learn', 'plant', 'cover', 'food', 'sun', 'four', 'between', 'state',
'keep', 'eye', 'never', 'last', 'let', 'thought', 'city', 'tree', 'cross', 'farm',
'hard', 'start', 'might', 'story', 'saw', 'far', 'sea', 'draw', 'left', 'late',
'run', 'don\'t', 'while', 'press', 'close', 'night', 'real', 'life', 'few', 'north'
];
const WORDS_TO_TEST = 100;
const gameAreaEl = document.getElementById('game-area');
const wordsContainerEl = document.getElementById('words-container');
const typingInputEl = document.getElementById('typing-input');
const timerEl = document.getElementById('timer');
const restartBtn = document.getElementById('restart-btn');
const resultsEl = document.getElementById('results');
const wpmEl = document.getElementById('wpm');
const accuracyEl = document.getElementById('accuracy');
const correctWordsEl = document.getElementById('correct-words');
const incorrectWordsEl = document.getElementById('incorrect-words');
let words = [];
let currentWordIndex = 0;
let correctCount = 0;
let incorrectCount = 0;
let timerInterval;
let startTime;
let gameActive = false;
function initializeTest() {
// Reset state
currentWordIndex = 0;
correctCount = 0;
incorrectCount = 0;
gameActive = false;
clearInterval(timerInterval);
// Show game, hide results
gameAreaEl.classList.remove('hidden');
resultsEl.classList.add('hidden');
// Reset UI
timerEl.textContent = "Time: 0:00";
typingInputEl.value = '';
typingInputEl.disabled = false;
wordsContainerEl.innerHTML = '';
// Generate and display words
words = generateWords(WORDS_TO_TEST);
words.forEach((word, index) => {
const wordSpan = document.createElement('span');
wordSpan.textContent = word;
wordSpan.classList.add('word');
wordSpan.id = `word-${index}`;
wordsContainerEl.appendChild(wordSpan);
});
updateWordHighlight();
typingInputEl.focus();
}
function generateWords(count) {
const shuffled = wordList.sort(() => 0.5 - Math.random());
return shuffled.slice(0, count);
}
function updateWordHighlight() {
// Remove previous highlight
const currentWordEl = document.querySelector('.word.current');
if (currentWordEl) currentWordEl.classList.remove('current');
// Add new highlight
const nextWordEl = document.getElementById(`word-${currentWordIndex}`);
if (nextWordEl) {
nextWordEl.classList.add('current');
// Scroll the word into view
nextWordEl.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
}
function startGame() {
if (gameActive) return;
gameActive = true;
startTime = new Date().getTime();
timerInterval = setInterval(updateTimer, 1000);
}
function updateTimer() {
const currentTime = new Date().getTime();
const elapsedTime = Math.floor((currentTime - startTime) / 1000);
const minutes = Math.floor(elapsedTime / 60);
const seconds = elapsedTime % 60;
timerEl.textContent = `Time: ${minutes}:${seconds.toString().padStart(2, '0')}`;
}
function checkWord() {
const typedValue = typingInputEl.value.trim();
if (typedValue === '') return;
const currentWord = words[currentWordIndex];
const currentWordEl = document.getElementById(`word-${currentWordIndex}`);
if (typedValue === currentWord) {
currentWordEl.classList.add('correct');
correctCount++;
} else {
currentWordEl.classList.add('incorrect');
incorrectCount++;
}
currentWordIndex++;
if (currentWordIndex >= words.length) {
endGame();
return;
}
updateWordHighlight();
typingInputEl.value = '';
}
function endGame() {
gameActive = false;
clearInterval(timerInterval);
typingInputEl.disabled = true;
const endTime = new Date().getTime();
const elapsedTimeInMinutes = (endTime - startTime) / 1000 / 60;
const calculatedWpm = Math.round(correctCount / elapsedTimeInMinutes) || 0;
const calculatedAccuracy = Math.round((correctCount / (correctCount + incorrectCount)) * 100) || 0;
wpmEl.textContent = calculatedWpm;
accuracyEl.textContent = `${calculatedAccuracy}%`;
correctWordsEl.textContent = correctCount;
incorrectWordsEl.textContent = incorrectCount;
gameAreaEl.classList.add('hidden');
resultsEl.classList.remove('hidden');
}
typingInputEl.addEventListener('keydown', (e) => {
if (!gameActive && e.key !== ' ' && e.key !== 'Enter' && e.key !== 'Tab') {
startGame();
}
if (e.key === ' ') {
e.preventDefault(); // Prevent space from being typed
checkWord();
}
});
// For mobile or autocorrect scenarios where space might not be a keydown event
typingInputEl.addEventListener('input', () => {
if (typingInputEl.value.endsWith(' ')) {
checkWord();
}
});
restartBtn.addEventListener('click', initializeTest);
// Initial setup
initializeTest();
});
</script>
</body>
</html>
``````html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Typing Speed Test</title>
<style>
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f5f5f5;
}
.container {
width: 80%;
max-width: 800px;
padding: 20px;
background-color: white;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
text-align: center;
}
#words {
font-size: 24px;
margin: 20px 0;
min-height: 60px;
color: #333;
}
#input {
font-size: 18px;
padding: 10px;
width: 80%;
border: 2px solid #ddd;
border-radius: 5px;
margin-bottom: 20px;
}
#input:focus {
outline: none;
border-color: #4d90fe;
}
#result {
font-size: 18px;
margin-top: 20px;
font-weight: bold;
}
.correct {
color: #3c763d;
}
.current {
border-bottom: 2px solid #4d90fe;
}
.incorrect {
color: #a94442;
text-decoration: underline;
}
#progress {
margin-top: 10px;
color: #666;
}
button {
background-color: #4CAF50;
color: white;
border: none;
padding: 10px 20px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 10px 2px;
cursor: pointer;
border-radius: 5px;
}
button:hover {
background-color: #45a049;
}
</style>
</head>
<body>
<div class="container">
<h1>Typing Speed Test</h1>
<p>Type the words below as quickly and accurately as possible.</p>
<div id="words"></div>
<input type="text" id="input" autocomplete="off" autofocus>
<div id="result"></div>
<div id="progress">Words: 0/100</div>
<button id="reset">Restart Test</button>
</div>
<script>
// Array of common words for the typing test
const wordList = [
"the", "be", "to", "of", "and", "a", "in", "that", "have", "I",
"it", "for", "not", "on", "with", "he", "as", "you", "do", "at",
"this", "but", "his", "by", "from", "they", "we", "say", "her", "she",
"or", "an", "will", "my", "one", "all", "would", "there", "their",
"what", "so", "up", "out", "if", "about", "who", "get", "which",
"go", "me", "when", "make", "can", "like", "time", "no", "just",
"him", "know", "take", "people", "into", "year", "your", "good",
"some", "could", "them", "see", "other", "than", "then", "now",
"look", "only", "come", "its", "over", "think", "also", "back",
"after", "use", "two", "how", "our", "work", "first", "well", "way",
"even", "new", "want", "because", "any", "these", "give", "day",
"most", "us", "again", "great", "free", "left", "right", "high",
"small", "large", "young", "old", "fast", "slow", "long", "short",
"next", "last", "early", "late", "true", "false", "open", "close",
"light", "dark", "warm", "cold", "hard", "soft", "near", "far",
"quick", "clean", "dirty", "easy", "difficult", "strong", "weak"
];
// Elements
const wordsElement = document.getElementById('words');
const inputElement = document.getElementById('input');
const resultElement = document.getElementById('result');
const progressElement = document.getElementById('progress');
const resetButton = document.getElementById('reset');
// Test variables
let currentWords = [];
let currentWordIndex = 0;
let startTime = null;
let finished = false;
let correctWords = 0;
// Generate random words for the test
function generateWords(count) {
const words = [];
for (let i = 0; i < count; i++) {
const randomIndex = Math.floor(Math.random() * wordList.length);
words.push(wordList[randomIndex]);
}
return words;
}
// Display the words in the UI
function displayWords() {
wordsElement.innerHTML = '';
currentWords.forEach((word, index) => {
const wordSpan = document.createElement('span');
wordSpan.textContent = word + ' ';
wordSpan.classList.add('word');
if (index === currentWordIndex) {
wordSpan.classList.add('current');
} else if (index < currentWordIndex) {
wordSpan.classList.add('correct');
}
wordsElement.appendChild(wordSpan);
});
}
// Initialize the test
function initTest() {
currentWords = generateWords(100);
currentWordIndex = 0;
correctWords = 0;
finished = false;
startTime = null;
inputElement.value = '';
inputElement.disabled = false;
resultElement.textContent = '';
progressElement.textContent = 'Words: 0/100';
displayWords();
inputElement.focus();
}
// Calculate WPM
function calculateWPM(correctWords, timeInMinutes) {
return Math.round(correctWords / timeInMinutes);
}
// Check the current input
function checkInput() {
if (finished) return;
const currentWord = currentWords[currentWordIndex];
const typedText = inputElement.value.trim();
// Start the timer on first keystroke
if (startTime === null && typedText.length > 0) {
startTime = new Date();
}
// Highlight the current word based on input
const wordSpans = document.querySelectorAll('.word');
wordSpans[currentWordIndex].classList.remove('correct', 'incorrect');
if (typedText === currentWord) {
wordSpans[currentWordIndex].classList.add('correct');
} else if (typedText && !currentWord.startsWith(typedText)) {
wordSpans[currentWordIndex].classList.add('incorrect');
}
// Check if the current word is complete
if (typedText === currentWord) {
currentWordIndex++;
inputElement.value = '';
correctWords++;
// Update progress
progressElement.textContent = `Words: ${currentWordIndex}/100`;
// Check if test is complete
if (currentWordIndex >= currentWords.length) {
finishTest();
return;
}
// Update current word highlighting
displayWords();
}
}
// Finish the test
function finishTest() {
finished = true;
inputElement.disabled = true;
const endTime = new Date();
const timeElapsed = (endTime - startTime) / 1000 / 60; // Convert to minutes
const wpm = calculateWPM(correctWords, timeElapsed);
resultElement.innerHTML = `
Test Complete!<br>
Words per minute: ${wpm}<br>
Accuracy: 100%<br>
Time: ${Math.round(timeElapsed * 60)} seconds
`;
}
// Event listeners
inputElement.addEventListener('input', checkInput);
inputElement.addEventListener('keydown', (e) => {
if (e.key === ' ') {
// Prevent space from being added if the word isn't complete
const currentWord = currentWords[currentWordIndex];
if (inputElement.value.trim() !== currentWord) {
e.preventDefault();
}
}
});
resetButton.addEventListener('click', initTest);
// Initialize on load
initTest();
</script>
</body>
</html>
``````html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript Typing Test</title>
<style>
body {
font-family: 'Segoe UI', Arial, sans-serif;
background: #f1f3f6;
padding: 0;
margin: 0;
display: flex;
height: 100vh;
align-items: center;
justify-content: center;
}
#container {
background: #fff;
border-radius: 10px;
padding: 30px;
max-width: 700px;
box-shadow: 0 6px 22px 0 rgba(60,90,130,0.12);
display: flex;
flex-direction: column;
align-items: center;
}
#words {
font-size: 1.5em;
letter-spacing: 1px;
line-height: 1.7;
margin-bottom: 20px;
word-wrap: break-word;
user-select: none;
}
.highlight {
background: #d3eafd;
border-radius: 3px;
padding: 0 2px;
}
.correct {
color: #34b233;
}
.incorrect {
color: #d94343;
background: #fde0de;
border-radius: 3px;
padding: 0 2px;
}
#input {
padding: 10px 16px;
font-size: 1em;
width: 60%;
max-width: 350px;
margin-bottom: 18px;
border: 1.5px solid #c0c0c2;
border-radius: 6px;
background: #f3f4f8;
outline: none;
transition: border .25s;
}
#input:focus { border: 1.5px solid #3978ec; }
#info, #results {
font-size: 1.1em;
margin: 10px 0;
}
#restartBtn {
display: none;
padding: 10px 24px;
border-radius: 5px;
border: none;
background: #3978ec;
color: #fff;
font-size: 1em;
cursor: pointer;
margin-top: 16px;
font-weight: 500;
transition: background .2s;
}
#restartBtn:hover {
background: #2559b6;
}
</style>
</head>
<body>
<div id="container">
<h2>Typing Speed Test</h2>
<div id="words"></div>
<input id="input" type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" autofocus />
<div id="info">Type the words above as fast and accurately as you can!</div>
<div id="results"></div>
<button id="restartBtn">Restart</button>
</div>
<script>
// A sample list of common English words. Expand as desired.
const WORD_LIST = [
"the","be","to","of","and","a","in","that","have","I","it","for","not","on","with","he",
"as","you","do","at","this","but","his","by","from","they","we","say","her","she","or","an","will",
"my","one","all","would","there","their","what","so","up","out","if","about","who","get","which","go","me",
"when","make","can","like","time","no","just","him","know","take","people","into","year","your","good","some",
"could","them","see","other","than","then","now","look","only","come","its","over","think","also","back","after",
"use","two","how","our","work","first","well","way","even","new","want","because","any","these","give","day","most","us",
"man","find","here","thing","more","need","life","woman","child","down","should","call","world","school",
"still","try","last","ask","never","long","might","great","right","too","big","little","place","old","tell"
];
// Generate 100 random words
function getRandomWords(n) {
let arr = [];
for (let i = 0; i < n; i++) {
arr.push(WORD_LIST[Math.floor(Math.random() * WORD_LIST.length)]);
}
return arr;
}
// State
let words = [];
let wordIndex = 0;
let charIndex = 0;
let testStarted = false;
let testFinished = false;
let startTime = null;
let endTime = null;
let correctWordCount = 0;
let totalTypedChars = 0;
let mistakes = 0;
// DOM
const wordsDisplay = document.getElementById('words');
const input = document.getElementById('input');
const info = document.getElementById('info');
const results = document.getElementById('results');
const restartBtn = document.getElementById('restartBtn');
function renderWords() {
wordsDisplay.innerHTML = '';
for(let i=0; i<words.length; i++) {
let span = document.createElement('span');
span.textContent = words[i];
span.id = 'word-' + i;
if(i === wordIndex) span.classList.add('highlight');
wordsDisplay.appendChild(span);
if(i < words.length - 1) wordsDisplay.appendChild(document.createTextNode(' '));
}
}
function highlightCurrentWord() {
for(let i=0; i<words.length; i++) {
let span = document.getElementById('word-'+i);
if(i === wordIndex) {
span.classList.add('highlight');
} else {
span.classList.remove('highlight');
}
}
}
function checkInput() {
let currentWord = words[wordIndex];
let typed = input.value;
let span = document.getElementById('word-' + wordIndex);
// Remove classes
span.classList.remove('correct','incorrect');
// Check for correctness so far
if(currentWord.startsWith(typed)) {
span.classList.remove('incorrect');
} else {
span.classList.add('incorrect');
}
// On space or word complete
if((typed.endsWith(' ') && typed.trim().length > 0) || typed === currentWord) {
const trimmedTyped = typed.trim();
// Update stats
if(trimmedTyped === currentWord) {
span.classList.remove('incorrect');
span.classList.add('correct');
correctWordCount++;
} else {
span.classList.add('incorrect');
mistakes++;
}
totalTypedChars += trimmedTyped.length;
wordIndex++;
input.value = '';
highlightCurrentWord();
if(wordIndex === words.length) {
finishTest();
return;
}
}
}
function finishTest() {
testFinished = true;
endTime = performance.now();
input.disabled = true;
let seconds = (endTime - startTime) / 1000;
let wpm = Math.round((correctWordCount / seconds) * 60*100)/100;
let grossWPM = Math.round((words.length / seconds) * 60*100)/100;
let accuracy = Math.round((correctWordCount / words.length) * 10000) / 100;
results.innerHTML = `
<b>Results:</b><br>
Time Taken: ${seconds.toFixed(2)}s<br>
Net WPM: <b>${wpm}</b><br>
Gross WPM: <b>${grossWPM}</b><br>
Words Correct: ${correctWordCount} / ${words.length}<br>
Mistakes: ${mistakes}<br>
Accuracy: <b>${accuracy}%</b>
`;
info.textContent = "Test completed! See results below.";
restartBtn.style.display = "inline-block";
}
// Event listeners
input.addEventListener('input', function() {
if(testFinished) return;
if(!testStarted && input.value.length > 0) {
testStarted = true;
startTime = performance.now();
info.textContent = "Timer started! Keep going!";
}
checkInput();
});
restartBtn.addEventListener('click', initializeTest);
// Initialization
function initializeTest() {
words = getRandomWords(100);
wordIndex = 0;
charIndex = 0;
testStarted = false;
testFinished = false;
correctWordCount = 0;
totalTypedChars = 0;
mistakes = 0;
input.disabled = false;
input.value = '';
results.innerHTML = '';
info.textContent = 'Type the words above as fast and accurately as you can!';
restartBtn.style.display = "none";
renderWords();
highlightCurrentWord();
setTimeout(()=>input.focus(),100);
}
// Allow pressing enter to restart
input.addEventListener('keydown', function(e) {
if(testFinished && e.key === 'Enter') {
initializeTest();
}
});
document.addEventListener('DOMContentLoaded', initializeTest);
</script>
</body>
</html>
``````html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Typing Speed Test</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
padding: 30px;
max-width: 600px;
margin: 0 auto;
}
#word-area {
font-size: 28px;
margin: 20px 0;
min-height: 36px;
}
#input-field {
width: 100%;
font-size: 18px;
padding: 10px;
}
#results {
margin-top: 30px;
font-size: 20px;
}
button {
margin-top: 15px;
padding: 10px 20px;
font-size: 16px;
}
</style>
</head>
<body>
<h1>Typing Speed Test</h1>
<div id="word-area"></div>
<input type="text" id="input-field" disabled>
<div id="results"></div>
<script>
const words = [
"apple", "banana", "cherry", "date", "elephant", "flower", "guitar", "happy", "island", "jungle",
"kangaroo", "laptop", "mountain", "network", "orange", "picture", "question", "robot", "sunshine", "tomorrow",
"umbrella", "vacation", "waterfall", "xylophone", "yellow", "zebra", "adventure", "butterfly", "celebrate", "discovery",
"elephant", "freedom", "guitarist", "hamburger", "important", "journey", "knowledge", "landscape", "microsoft", "notebook",
"ocean", "penguin", "queen", "rainbow", "strawberry", "telescope", "umbrella", "volcanic", "whale", "xenon",
"yogurt", "zookeeper", "alligator", "birthday", "calendar", "dinosaur", "eclipse", "firefly", "galaxy", "horizon",
"internet", "jellyfish", "kangaroo", "lightbulb", "mosquito", "nightfall", "ostrich", "pandemic", "quartz", "rattlesnake",
"squirrel", "teapot", "umbrella", "vacuum", "waterpark", "xylophone", "yacht", "zeppelin", "abandoned", "butterfly",
"catastrophe", "dangerous", "disappear", "earthquake", "fantastic", "giraffe", "hazardous", "incredible", "vaccinate",
"jellyfish", "kangaroo", "labyrinth", "magnitude", "nightmare", "optimistic", "pharmaceutical", "radiation", "spectacular"
];
let shuffledWords = [], currentIndex = 0;
let startTime = null, resultsDisplayed = false;
function shuffle(array) {
const copy = [...array];
for (let i = copy.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[copy[i], copy[j]] = [copy[j], copy[i]];
}
return copy;
}
function startTest() {
shuffledWords = shuffle(words);
currentIndex = 0;
startTime = null;
resultsDisplayed = false;
document.getElementById('word-area').textContent = shuffledWords[currentIndex];
document.getElementById('input-field').value = '';
document.getElementById('input-field').disabled = false;
document.getElementById('results').innerHTML = '';
}
function finishTest(duration) {
if (resultsDisplayed) return;
resultsDisplayed = true;
const wpm = Math.round((100 / duration) * 60);
document.getElementById('word-area').textContent = '';
document.getElementById('input-field').disabled = true;
document.getElementById('results').innerHTML = `
<strong>Test completed!</strong><br>
WPM: ${wpm}<br>
Time: ${Math.round(duration * 60)} seconds<br>
<button onclick="startTest()">Retry Test</button>
`;
}
document.addEventListener("DOMContentLoaded", () => {
document.getElementById('input-field').addEventListener('input', () => {
if (resultsDisplayed) return;
const inputField = document.getElementById('input-field');
const wordArea = document.getElementById('word-area');
const currentText = inputField.value.trim();
const currentWord = wordArea.textContent;
// Start timer on first input
if (!startTime && currentText.length > 0) {
startTime = Date.now();
}
if (currentText === currentWord && currentText !== '') {
currentIndex++;
inputField.value = '';
if (currentIndex < 100) {
wordArea.textContent = shuffledWords[currentIndex];
} else {
const duration = (Date.now() - startTime) / 1000 / 60;
finishTest(duration);
}
}
});
startTest();
});
</script>
</body>
</html>
``````html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>JavaScript Typing Test</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background: #f2f5f9;
color: #1a1a1a;
display: flex;
justify-content: center;
padding: 2rem;
}
.test-card {
background: #fff;
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.05);
border-radius: 12px;
padding: 2rem 3rem;
max-width: 650px;
width: 100%;
}
h1 {
margin-top: 0;
font-size: 1.6rem;
}
.stats {
margin-bottom: 1rem;
display: flex;
gap: 1rem;
font-size: 1.1rem;
}
.stats span {
font-weight: 700;
}
.word-display {
font-size: 2.2rem;
line-height: 1.4;
}
#current-word {
font-weight: 700;
}
#input-area {
margin-top: 1.5rem;
}
#inputBox {
width: 100%;
font-size: 1.4rem;
padding: 0.75rem;
border-radius: 8px;
border: 1px solid #ccc;
outline: none;
transition: box-shadow 0.2s;
}
.correct {
color: #2ecc71;
}
.incorrect {
color: #e74c3c;
text-decoration: underline;
}
.completed {
color: #9b9b9b;
}
</style>
</head>
<body>
<div class="test-card">
<h1>100-word JavaScript Typing Test</h1>
<div class="stats">
<p>Progress: <span id="progress">0/100</span></p>
<p>WPM: <span id="wpm">0</span></p>
<p>Time: <span id="timer">0.0s</span></p>
</div>
<div class="word-display" id="wordDisplay"></div>
<div id="input-area">
<input id="inputBox" autocomplete="off" placeholder="Start typing here..." />
</div>
</div>
<script>
const WORD_POOL = [
"abandon","ability","able","about","above","absent","absolute","absorb","abstract","absurd",
"abuse","access","accident","account","accuse","ache","achieve","acid","across","act",
"active","actor","actual","adapt","add","address","admit","adult","advance","advice",
"aerobic","affair","afraid","again","age","agency","agenda","agent","agree","ahead","aim",
"air","alarm","album","alcohol","alert","alike","alive","allow","almost","alone","alpha",
"already","also","alter","always","amaze","among","amount","amuse","analysis","analyst",
"anchor","ancient","anger","angle","angry","animal","ankle","announce","annual","anxiety",
"anxious","anybody","apart","apologize","appeal","appear","apple","apply","appoint","approve",
"area","argue","arise","armor","army","around","arrange","arrest","arrive","artist"
];
/* --- DOM shortcuts --- */
const $display = document.getElementById('wordDisplay');
const $inputBox = document.getElementById('inputBox');
const $progress = document.getElementById('progress');
const $wpm = document.getElementById('wpm');
const $timer = document.getElementById('timer');
/* --- Game state --- */
let words = [];
let currIndex = 0;
let startTime = 0;
let timerHandle = 0;
let gameDone = false;
/* --- Helpers --- */
const randomWords = (n) =>
[...Array(n)].map(() => WORD_POOL[(Math.random() * WORD_POOL.length) | 0]);
const resetGame = () => {
currIndex = 0;
gameDone = false;
words = randomWords(100);
startTime = 0;
$inputBox.removeAttribute('disabled');
$inputBox.value = '';
$inputBox.focus();
renderWords();
updateStats();
if (timerHandle) clearInterval(timerHandle);
$timer.textContent = '0.0s';
};
const renderWords = () => {
let html = '';
words.forEach((w, i) => {
if (i === currIndex) {
html += `<span id="current-word">${w}</span> `;
} else if (i < currIndex) {
html += `<span class="completed">${w}</span> `;
} else {
html += w + ' ';
}
});
$display.innerHTML = html;
};
const updateStats = () => {
$progress.textContent = `${currIndex}/100`;
if (!startTime || currIndex === 0) {
$wpm.textContent = 0;
return;
}
const minutes = (Date.now() - startTime) / 60000;
const wpm = Math.round(currIndex / minutes) || 0;
$wpm.textContent = wpm;
};
const startTimer = () => {
startTime = Date.now();
timerHandle = setInterval(() => {
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
$timer.textContent = `${elapsed}s`;
}, 100);
};
const endGame = () => {
gameDone = true;
clearInterval(timerHandle);
const minutes = (Date.now() - startTime) / 60000;
const wpm = Math.round(words.length / minutes) | 0;
$inputBox.setAttribute('disabled', true);
setTimeout(() =>
alert(`Finished!\nTotal time: ${((Date.now() - startTime) / 1000).toFixed(1)} s\nWPM: ${wpm}`),
10
);
};
/* --- Event Handlers --- */
$inputBox.addEventListener('keydown', (e) => {
if (gameDone) return;
if (!startTime) startTimer(); // first key
});
$inputBox.addEventListener('input', () => {
if (gameDone) return;
const typed = $inputBox.value.trimEnd();
const target = words[currIndex];
const currentSpan = document.getElementById('current-word');
/* Correct so far */
if (target.startsWith(typed)) {
if (typed === target) {
/* move to next word */
currIndex++;
updateStats();
$inputBox.value = '';
if (currIndex >= 100) {
endGame();
return;
}
renderWords();
} else {
/* partial */
currentSpan.className = '';
}
} else {
/* error state (optional visual cue) */
currentSpan.className = 'incorrect';
}
});
/* Kick-off */
resetGame();
</script>
</body>
</html>
```**Typing Test Implementation**
================================
Below is a basic implementation of a typing test in JavaScript, HTML, and CSS. This test displays 100 random words and measures the user's typing speed.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Typing Test</title>
<style>
body {
font-family: Arial, sans-serif;
}
#typing-test {
width: 800px;
margin: 40px auto;
text-align: center;
}
#typing-input {
width: 100%;
height: 30px;
font-size: 18px;
padding: 10px;
box-sizing: border-box;
}
#word-display {
font-size: 24px;
margin-bottom: 20px;
}
#result {
font-size: 18px;
margin-top: 20px;
}
</style>
</head>
<body>
<div id="typing-test">
<div id="word-display"></div>
<input id="typing-input" type="text" autocomplete="off">
<div id="result"></div>
</div>
<script>
// List of words for the typing test
const words = ["apple", "banana", "cherry", "date", "elderberry", "fig", "grape", "honeydew", "ice cream", "jackfruit", "kiwi", "lemon", "mango", "nectarine", "orange", "pineapple", "quince", "raspberry", "strawberry", "tangerine", "ugli fruit", "victoria plum", "watermelon", "xigua", "yellow passionfruit", "zucchini"];
// Function to get a random word from the list
function getRandomWord() {
return words[Math.floor(Math.random() * words.length)];
}
// Initialize variables
let wordCount = 0;
let startTime = null;
let currentWord = getRandomWord();
let typedWord = '';
// Display the first word
document.getElementById('word-display').innerText = currentWord;
// Event listener for typing input
document.getElementById('typing-input').addEventListener('input', (e) => {
const input = e.target.value.trim();
// Check if the typed word is correct
if (input === currentWord) {
wordCount++;
typedWord = '';
// Check if 100 words have been typed
if (wordCount >= 100) {
const endTime = new Date().getTime();
const elapsed = (endTime - startTime) / 1000 / 60; // minutes
const wpm = Math.round(wordCount / elapsed);
document.getElementById('result').innerText = `Your typing speed is ${wpm} words per minute.`;
document.getElementById('typing-input').disabled = true;
} else {
// Display the next word
currentWord = getRandomWord();
document.getElementById('word-display').innerText = currentWord;
e.target.value = '';
}
// Record the start time if it's the first word
if (startTime === null) {
startTime = new Date().getTime();
}
}
});
// Focus on the input field
document.getElementById('typing-input').focus();
</script>
</body>
</html>
```
**How it works:**
1. The HTML structure includes a `div` to display the current word, an `input` field for typing, and a `div` to display the result.
2. The JavaScript code initializes an array of words and selects a random word to display.
3. When the user types a word and presses the correct word, the code increments the word count, records the start time if it's the first word, and displays the next random word.
4. Once 100 words have been typed, the code calculates the typing speed in words per minute (wpm) and displays the result.
5. The input field is disabled after 100 words have been typed to prevent further input.
You can save this code as an HTML file and open it in a web browser to run the typing test.```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Typing Speed Test</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Courier New', monospace;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
color: #333;
}
.container {
background: white;
border-radius: 15px;
padding: 40px;
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1);
max-width: 800px;
width: 90%;
}
.header {
text-align: center;
margin-bottom: 30px;
}
.title {
font-size: 2.5em;
color: #667eea;
margin-bottom: 10px;
}
.stats {
display: flex;
justify-content: space-around;
margin-bottom: 30px;
background: #f8f9fa;
padding: 20px;
border-radius: 10px;
}
.stat-item {
text-align: center;
}
.stat-label {
font-size: 0.9em;
color: #666;
margin-bottom: 5px;
}
.stat-value {
font-size: 1.5em;
font-weight: bold;
color: #333;
}
.text-display {
background: #f8f9fa;
padding: 30px;
border-radius: 10px;
margin-bottom: 20px;
font-size: 1.2em;
line-height: 2;
min-height: 150px;
overflow: hidden;
}
.word {
margin-right: 8px;
padding: 2px 4px;
border-radius: 4px;
transition: all 0.2s;
}
.word.current {
background: #667eea;
color: white;
}
.word.correct {
background: #28a745;
color: white;
}
.word.incorrect {
background: #dc3545;
color: white;
}
.input-area {
margin-bottom: 20px;
}
.text-input {
width: 100%;
padding: 15px;
font-size: 1.1em;
font-family: 'Courier New', monospace;
border: 2px solid #ddd;
border-radius: 8px;
outline: none;
transition: border-color 0.3s;
}
.text-input:focus {
border-color: #667eea;
}
.controls {
display: flex;
justify-content: center;
gap: 15px;
margin-bottom: 20px;
}
.btn {
padding: 12px 24px;
font-size: 1em;
border: none;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s;
font-family: inherit;
}
.btn-primary {
background: #667eea;
color: white;
}
.btn-primary:hover {
background: #5a67d8;
}
.btn-secondary {
background: #6c757d;
color: white;
}
.btn-secondary:hover {
background: #5a6268;
}
.results {
background: #e8f5e8;
padding: 20px;
border-radius: 10px;
text-align: center;
display: none;
}
.results h3 {
color: #28a745;
margin-bottom: 15px;
font-size: 1.5em;
}
.progress-bar {
width: 100%;
height: 8px;
background: #e0e0e0;
border-radius: 4px;
overflow: hidden;
margin-bottom: 20px;
}
.progress-fill {
height: 100%;
background: #667eea;
width: 0%;
transition: width 0.3s;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1 class="title">Typing Speed Test</h1>
<p>Type the words as they appear. Test your speed with 100 words!</p>
</div>
<div class="progress-bar">
<div class="progress-fill" id="progressFill"></div>
</div>
<div class="stats">
<div class="stat-item">
<div class="stat-label">WPM</div>
<div class="stat-value" id="wpm">0</div>
</div>
<div class="stat-item">
<div class="stat-label">Accuracy</div>
<div class="stat-value" id="accuracy">100%</div>
</div>
<div class="stat-item">
<div class="stat-label">Time</div>
<div class="stat-value" id="time">0s</div>
</div>
<div class="stat-item">
<div class="stat-label">Words</div>
<div class="stat-value" id="wordCount">0/100</div>
</div>
</div>
<div class="text-display" id="textDisplay"></div>
<div class="input-area">
<input type="text" class="text-input" id="textInput" placeholder="Click 'Start Test' to begin..." disabled>
</div>
<div class="controls">
<button class="btn btn-primary" id="startBtn" onclick="startTest()">Start Test</button>
<button class="btn btn-secondary" id="resetBtn" onclick="resetTest()">Reset</button>
</div>
<div class="results" id="results">
<h3>Test Complete!</h3>
<div id="finalStats"></div>
</div>
</div>
<script>
const words = [
'the', 'be', 'to', 'of', 'and', 'in', 'it', 'you', 'that', 'he',
'was', 'for', 'on', 'are', 'as', 'with', 'his', 'they', 'at', 'one',
'have', 'this', 'from', 'or', 'had', 'by', 'word', 'but', 'not', 'what',
'all', 'were', 'we', 'when', 'your', 'can', 'said', 'there', 'each', 'which',
'do', 'how', 'their', 'if', 'will', 'up', 'other', 'about', 'out', 'many',
'then', 'them', 'these', 'so', 'some', 'her', 'would', 'make', 'like', 'into',
'him', 'time', 'has', 'two', 'more', 'very', 'after', 'words', 'long', 'than',
'way', 'call', 'just', 'where', 'most', 'know', 'get', 'through', 'back', 'much',
'before', 'go', 'good', 'new', 'write', 'our', 'used', 'me', 'man', 'too',
'any', 'day', 'same', 'right', 'look', 'think', 'also', 'around', 'another', 'came',
'come', 'work', 'three', 'must', 'because', 'does', 'part', 'even', 'place', 'well',
'such', 'here', 'take', 'why', 'help', 'put', 'different', 'away', 'again', 'off',
'went', 'old', 'number', 'great', 'tell', 'men', 'say', 'small', 'every', 'found',
'still', 'between', 'name', 'should', 'home', 'big', 'give', 'air', 'line', 'set'
];
let currentWords = [];
let currentWordIndex = 0;
let currentInput = '';
let startTime = null;
let isTestActive = false;
let correctWords = 0;
let totalTypedWords = 0;
let timer = null;
function generateWords() {
currentWords = [];
for (let i = 0; i < 100; i++) {
currentWords.push(words[Math.floor(Math.random() * words.length)]);
}
}
function displayWords() {
const textDisplay = document.getElementById('textDisplay');
textDisplay.innerHTML = '';
currentWords.forEach((word, index) => {
const span = document.createElement('span');
span.className = 'word';
span.textContent = word;
span.id = `word-${index}`;
if (index === currentWordIndex) {
span.classList.add('current');
}
textDisplay.appendChild(span);
});
}
function startTest() {
generateWords();
displayWords();
currentWordIndex = 0;
currentInput = '';
correctWords = 0;
totalTypedWords = 0;
startTime = Date.now();
isTestActive = true;
const textInput = document.getElementById('textInput');
textInput.disabled = false;
textInput.placeholder = 'Start typing...';
textInput.focus();
textInput.value = '';
document.getElementById('startBtn').disabled = true;
document.getElementById('results').style.display = 'none';
updateStats();
startTimer();
}
function resetTest() {
isTestActive = false;
clearInterval(timer);
currentWordIndex = 0;
currentInput = '';
correctWords = 0;
totalTypedWords = 0;
startTime = null;
const textInput = document.getElementById('textInput');
textInput.disabled = true;
textInput.placeholder = 'Click "Start Test" to begin...';
textInput.value = '';
document.getElementById('startBtn').disabled = false;
document.getElementById('results').style.display = 'none';
document.getElementById('textDisplay').innerHTML = '<p style="text-align: center; color: #666;">Click "Start Test" to begin the typing test!</p>';
updateStats();
updateProgress();
}
function startTimer() {
timer = setInterval(updateStats, 100);
}
function updateStats() {
const timeElapsed = startTime ? (Date.now() - startTime) / 1000 : 0;
const minutes = timeElapsed / 60;
// Calculate WPM
const wpm = minutes > 0 ? Math.round(correctWords / minutes) : 0;
// Calculate accuracy
const accuracy = totalTypedWords > 0 ? Math.round((correctWords / totalTypedWords) * 100) : 100;
document.getElementById('wpm').textContent = wpm;
document.getElementById('accuracy').textContent = accuracy + '%';
document.getElementById('time').textContent = Math.round(timeElapsed) + 's';
document.getElementById('wordCount').textContent = `${correctWords}/100`;
updateProgress();
}
function updateProgress() {
const progress = (correctWords / 100) * 100;
document.getElementById('progressFill').style.width = progress + '%';
}
function checkWord() {
const currentWord = currentWords[currentWordIndex];
const wordElement = document.getElementById(`word-${currentWordIndex}`);
totalTypedWords++;
if (currentInput.trim() === currentWord) {
correctWords++;
wordElement.classList.remove('current');
wordElement.classList.add('correct');
} else {
wordElement.classList.remove('current');
wordElement.classList.add('incorrect');
}
currentWordIndex++;
currentInput = '';
if (currentWordIndex < currentWords.length) {
document.getElementById(`word-${currentWordIndex}`).classList.add('current');
// Scroll to current word if needed
const currentWordElement = document.getElementById(`word-${currentWordIndex}`);
currentWordElement.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
if (currentWordIndex >= 100) {
finishTest();
}
}
function finishTest() {
isTestActive = false;
clearInterval(timer);
const timeElapsed = (Date.now() - startTime) / 1000;
const minutes = timeElapsed / 60;
const wpm = Math.round(correctWords / minutes);
const accuracy = Math.round((correctWords / totalTypedWords) * 100);
document.getElementById('textInput').disabled = true;
document.getElementById('startBtn').disabled = false;
const results = document.getElementById('results');
const finalStats = document.getElementById('finalStats');
finalStats.innerHTML = `
<p><strong>Words Per Minute:</strong> ${wpm}</p>
<p><strong>Accuracy:</strong> ${accuracy}%</p>
<p><strong>Total Time:</strong> ${Math.round(timeElapsed)} seconds</p>
<p><strong>Correct Words:</strong> ${correctWords}/100</p>
`;
results.style.display = 'block';
}
document.getElementById('textInput').addEventListener('input', function(e) {
if (!isTestActive) return;
currentInput = e.target.value;
// Check if user pressed space or finished typing the word
if (currentInput.endsWith(' ') || currentInput === currentWords[currentWordIndex]) {
if (currentInput.endsWith(' ')) {
currentInput = currentInput.slice(0, -1); // Remove the space
}
checkWord();
e.target.value = '';
}
});
document.getElementById('textInput').addEventListener('keydown', function(e) {
if (!isTestActive) return;
// Handle Enter key as word completion
if (e.key === 'Enter') {
e.preventDefault();
checkWord();
e.target.value = '';
}
});
// Initialize the display
resetTest();
</script>
</body>
</html>
```
This typing test includes:
**Features:**
- 100 random words from a common word list
- Real-time WPM (Words Per Minute) calculation
- Accuracy percentage tracking
- Progress bar showing completion
- Timer showing elapsed time
- Visual feedback for correct/incorrect words
- Responsive design with attractive styling
**How to use:**
1. Click "Start Test" to begin
2. Type each word as it appears (highlighted in blue)
3. Press Space or Enter to move to the next word
4. Words turn green when correct, red when incorrect
5. Stats update in real-time
6. Test completes automatically after 100 words
**Key metrics tracked:**
- **WPM**: Words per minute based on correct words
- **Accuracy**: Percentage of correctly typed words
- **Time**: Total elapsed time
- **Progress**: Visual progress bar and word counter
The test uses a pool of common English words and randomly selects 100 for each test session. You can reset and start over at any time!