├── README.md ├── aa.html ├── style.css └── script.js /README.md: -------------------------------------------------------------------------------- 1 | # HTML-2 -------------------------------------------------------------------------------- /aa.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Typing Test 5 | 6 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |

Time: 0s

17 |

Mistakes: 0

18 |
19 |
24 | 29 | 30 | 31 |
32 |

Result

33 |
34 |

Accuracy:

35 |

Speed:

36 |
37 |
38 |
39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | * { 2 | padding: 0; 3 | margin: 0; 4 | box-sizing: border-box; 5 | font-family: "Poppins", sans-serif; 6 | } 7 | body { 8 | background-color: #dd3b12dc; 9 | } 10 | .container { 11 | width: 80vmin; 12 | padding: 50px 30px; 13 | background-color: #ffffff; 14 | position: absolute; 15 | transform: translate(-50%, 50%); 16 | top: 50%; 17 | left: 50%; 18 | border-radius: 10px; 19 | box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15); 20 | } 21 | .stats { 22 | text-align: right; 23 | font-size: 18px; 24 | margin-bottom: 30px; 25 | } 26 | .stats span { 27 | font-weight: 600; 28 | } 29 | #quote { 30 | text-align: justify; 31 | margin: 50px 0 30px 0; 32 | } 33 | textarea { 34 | resize: none; 35 | width: 100%; 36 | border-radius: 5px; 37 | padding: 10px 5px; 38 | font-size: 16px; 39 | } 40 | button { 41 | float: right; 42 | margin-top: 20px; 43 | background-color: #30f662; 44 | color: #39078a; 45 | border: none; 46 | padding: 10px 30px; 47 | border-radius: 5px; 48 | font-size: 18px; 49 | } 50 | .result { 51 | margin-top: 40px; 52 | display: none; 53 | } 54 | .result h3 { 55 | text-align: center; 56 | margin-bottom: 20px; 57 | font-size: 22px; 58 | } 59 | .wrapper { 60 | display: flex; 61 | justify-content: space-around; 62 | } 63 | .wrapper span { 64 | font-weight: 600; 65 | } 66 | .success { 67 | color: #d462a9; 68 | } 69 | .fail { 70 | color: #e81c4e; 71 | } -------------------------------------------------------------------------------- /script.js: -------------------------------------------------------------------------------- 1 | //Random Quotes Api URL 2 | const quoteApiUrl = "https://api.quotable.io/random?minLength=80&maxLength=100"; 3 | const quoteSection = document.getElementById("quote"); 4 | const userInput = document.getElementById("quote-input"); 5 | let quote = ""; 6 | let time = 60; 7 | let timer = ""; 8 | let mistakes = 0; 9 | 10 | //Display random quotes 11 | const renderNewQuote = async () => { 12 | //Fetch contents from url 13 | const response = await fetch(quoteApiUrl); 14 | 15 | //Store response 16 | let data = await response.json(); 17 | 18 | //Access quote 19 | quote = data.content; 20 | 21 | //Array of characters in the quote 22 | let arr = quote.split("").map((value) => { 23 | //wrap the characters in a span tag 24 | return "" + value + ""; 25 | }); 26 | //join array for displaying 27 | quoteSection.innerHTML += arr.join(""); 28 | }; 29 | 30 | //Logic for comparing input words with quote 31 | userInput.addEventListener("input", () => { 32 | let quoteChars = document.querySelectorAll(".quote-chars"); 33 | //Create an arrat from received span tags 34 | quoteChars = Array.from(quoteChars); 35 | 36 | //array of user input characters 37 | let userInputChars = userInput.value.split(""); 38 | 39 | //loop through each character in quote 40 | quoteChars.forEach((char, index) => { 41 | //Check if char(quote character) = userInputChars[index](input character) 42 | if (char.innerText == userInputChars[index]) { 43 | char.classList.add("success"); 44 | } 45 | //If user hasn't entered anything or backspaced 46 | else if (userInputChars[index] == null) { 47 | //Remove class if any 48 | if (char.classList.contains("success")) { 49 | char.classList.remove("success"); 50 | } else { 51 | char.classList.remove("fail"); 52 | } 53 | } 54 | //If user enter wrong character 55 | else { 56 | //Checks if we alreasy have added fail class 57 | if (!char.classList.contains("fail")) { 58 | //increment and display mistakes 59 | mistakes += 1; 60 | char.classList.add("fail"); 61 | } 62 | document.getElementById("mistakes").innerText = mistakes; 63 | } 64 | //Returns true if all the characters are entered correctly 65 | let check = quoteChars.every((element) => { 66 | return element.classList.contains("success"); 67 | }); 68 | //End test if all characters are correct 69 | if (check) { 70 | displayResult(); 71 | } 72 | }); 73 | }); 74 | 75 | //Update Timer on screen 76 | function updateTimer() { 77 | if (time == 0) { 78 | //End test if timer reaches 0 79 | displayResult(); 80 | } else { 81 | document.getElementById("timer").innerText = --time + "s"; 82 | } 83 | } 84 | 85 | //Sets timer 86 | const timeReduce = () => { 87 | time = 60; 88 | timer = setInterval(updateTimer, 1000); 89 | }; 90 | 91 | //End Test 92 | const displayResult = () => { 93 | //display result div 94 | document.querySelector(".result").style.display = "block"; 95 | clearInterval(timer); 96 | document.getElementById("stop-test").style.display = "none"; 97 | userInput.disabled = true; 98 | let timeTaken = 1; 99 | if (time != 0) { 100 | timeTaken = (60 - time) / 100; 101 | } 102 | document.getElementById("wpm").innerText = 103 | (userInput.value.length / 5 / timeTaken).toFixed(2) + " wpm"; 104 | document.getElementById("accuracy").innerText = 105 | Math.round( 106 | ((userInput.value.length - mistakes) / userInput.value.length) * 100 107 | ) + " %"; 108 | }; 109 | 110 | //Start Test 111 | const startTest = () => { 112 | mistakes = 0; 113 | timer = ""; 114 | userInput.disabled = false; 115 | timeReduce(); 116 | document.getElementById("start-test").style.display = "none"; 117 | document.getElementById("stop-test").style.display = "block"; 118 | }; 119 | 120 | window.onload = () => { 121 | userInput.value = ""; 122 | document.getElementById("start-test").style.display = "block"; 123 | document.getElementById("stop-test").style.display = "none"; 124 | userInput.disabled = true; 125 | renderNewQuote(); 126 | }; --------------------------------------------------------------------------------