├── 03-Translator ├── .vscode │ └── settings.json ├── img │ ├── icon.png │ ├── DemoDarkImg.png │ └── DemoLightImg.png ├── README.md ├── index.html ├── js │ ├── countries.js │ └── script.js └── css │ └── style.css ├── 05-TypingTest ├── README.md ├── img │ ├── logo.png │ └── pageDemo.png ├── css │ └── style.css ├── index.html └── js │ └── script.js ├── 06-SnakeGame ├── README.md ├── img │ ├── icon.png │ └── pageDemo.png ├── index.html ├── css │ └── style.css └── js │ └── script.js ├── 07-UrlShorter ├── README.md ├── img │ └── pageDemo.png ├── js │ └── script.js ├── css │ └── style.css └── index.html ├── 08-2048Game ├── README.md ├── img │ ├── icon.png │ └── pageDemo.png ├── index.html ├── css │ └── style.css └── js │ └── script.js ├── 04-QRCodeGenerator ├── README.md ├── img │ ├── logo.png │ ├── QRCode.png │ └── PageDemo.png ├── css │ └── style.css ├── index.html └── js │ └── script.js ├── 02-TextToSpeech ├── README.md ├── img │ ├── PageDemo.png │ └── pagelogo.png ├── index.html ├── js │ └── script.js └── css │ └── style.css ├── 01-PixelArtPalette ├── img │ ├── PageDemo.png │ ├── pixelIcon.png │ └── ScreenShot.png ├── README.md ├── index.html ├── js │ └── main.js └── css │ └── style.css └── README.md /03-Translator/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "liveServer.settings.port": 5501 3 | } -------------------------------------------------------------------------------- /05-TypingTest/README.md: -------------------------------------------------------------------------------- 1 | ## Page Demo - 2 | 3 | 4 | -------------------------------------------------------------------------------- /06-SnakeGame/README.md: -------------------------------------------------------------------------------- 1 | ## Page Demo - 2 | 3 | 4 | -------------------------------------------------------------------------------- /07-UrlShorter/README.md: -------------------------------------------------------------------------------- 1 | ## Page Demo - 2 | 3 | 4 | -------------------------------------------------------------------------------- /08-2048Game/README.md: -------------------------------------------------------------------------------- 1 | ## Page Demo - 2 | 3 | 4 | -------------------------------------------------------------------------------- /04-QRCodeGenerator/README.md: -------------------------------------------------------------------------------- 1 | ## Page Demo - 2 | 3 | 4 | -------------------------------------------------------------------------------- /08-2048Game/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfaarghya/100_Days-100_JavaScript/main/08-2048Game/img/icon.png -------------------------------------------------------------------------------- /03-Translator/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfaarghya/100_Days-100_JavaScript/main/03-Translator/img/icon.png -------------------------------------------------------------------------------- /05-TypingTest/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfaarghya/100_Days-100_JavaScript/main/05-TypingTest/img/logo.png -------------------------------------------------------------------------------- /06-SnakeGame/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfaarghya/100_Days-100_JavaScript/main/06-SnakeGame/img/icon.png -------------------------------------------------------------------------------- /06-SnakeGame/img/pageDemo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfaarghya/100_Days-100_JavaScript/main/06-SnakeGame/img/pageDemo.png -------------------------------------------------------------------------------- /08-2048Game/img/pageDemo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfaarghya/100_Days-100_JavaScript/main/08-2048Game/img/pageDemo.png -------------------------------------------------------------------------------- /04-QRCodeGenerator/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfaarghya/100_Days-100_JavaScript/main/04-QRCodeGenerator/img/logo.png -------------------------------------------------------------------------------- /05-TypingTest/img/pageDemo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfaarghya/100_Days-100_JavaScript/main/05-TypingTest/img/pageDemo.png -------------------------------------------------------------------------------- /07-UrlShorter/img/pageDemo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfaarghya/100_Days-100_JavaScript/main/07-UrlShorter/img/pageDemo.png -------------------------------------------------------------------------------- /02-TextToSpeech/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /02-TextToSpeech/img/PageDemo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfaarghya/100_Days-100_JavaScript/main/02-TextToSpeech/img/PageDemo.png -------------------------------------------------------------------------------- /02-TextToSpeech/img/pagelogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfaarghya/100_Days-100_JavaScript/main/02-TextToSpeech/img/pagelogo.png -------------------------------------------------------------------------------- /03-Translator/img/DemoDarkImg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfaarghya/100_Days-100_JavaScript/main/03-Translator/img/DemoDarkImg.png -------------------------------------------------------------------------------- /03-Translator/img/DemoLightImg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfaarghya/100_Days-100_JavaScript/main/03-Translator/img/DemoLightImg.png -------------------------------------------------------------------------------- /04-QRCodeGenerator/img/QRCode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfaarghya/100_Days-100_JavaScript/main/04-QRCodeGenerator/img/QRCode.png -------------------------------------------------------------------------------- /01-PixelArtPalette/img/PageDemo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfaarghya/100_Days-100_JavaScript/main/01-PixelArtPalette/img/PageDemo.png -------------------------------------------------------------------------------- /01-PixelArtPalette/img/pixelIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfaarghya/100_Days-100_JavaScript/main/01-PixelArtPalette/img/pixelIcon.png -------------------------------------------------------------------------------- /04-QRCodeGenerator/img/PageDemo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfaarghya/100_Days-100_JavaScript/main/04-QRCodeGenerator/img/PageDemo.png -------------------------------------------------------------------------------- /01-PixelArtPalette/img/ScreenShot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alfaarghya/100_Days-100_JavaScript/main/01-PixelArtPalette/img/ScreenShot.png -------------------------------------------------------------------------------- /01-PixelArtPalette/README.md: -------------------------------------------------------------------------------- 1 | # PixelArtPalette 2 | This is Pixel Art Palette.....here we can draw 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /03-Translator/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /07-UrlShorter/js/script.js: -------------------------------------------------------------------------------- 1 | let tinyUrlElement = document.getElementById("tiny-url"); 2 | const tinyUrl = () => { 3 | let url = document.getElementById("url").value; 4 | let apiUrl = "https://tinyurl.com/api-create.php?url=" + encodeURIComponent(url); 5 | 6 | fetch(apiUrl) 7 | .then(res => res.text()) 8 | .then(data => { 9 | tinyUrlElement.value = data; 10 | }) 11 | .catch(err => { 12 | tinyUrlElement.value = "Error : Unable to Generate"; 13 | }); 14 | } 15 | 16 | document.getElementById("short-btn").addEventListener("click", tinyUrl); 17 | document.getElementById("copy-btn").addEventListener("click", () => { 18 | navigator.clipboard.writeText(tinyUrlElement.value) 19 | }); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 100_Days-100_JavaScript 2 | 3 | I am learning JavaScript. My goal is to implement 100 JS projects beside learning. 4 | Currently I am working on 7 no mini-project. 5 | 6 | ## #day1 PixelArtPalette 7 | 8 | 9 | 10 | ## #day2 Text to Speech 11 | 12 | 13 | 14 | ## #day3 Translate App 15 | 16 | 17 | 18 | ## #day4 QR Code Generator 19 | 20 | 21 | 22 | ## #day5 Typing Test 23 | 24 | 25 | 26 | ## #day6 Snake game 27 | 28 | 29 | 30 | ## #day7 Url Shorter 31 | 32 | 33 | 34 | ## #day8 Url Shorter 35 | 36 | 37 | -------------------------------------------------------------------------------- /06-SnakeGame/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Snake Game 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | Score: 0 18 | High Score: 0 19 |
20 | 21 |
22 | 23 |
24 | 25 | 26 | 27 | 28 |
29 |
30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /07-UrlShorter/css/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | 6 | body { 7 | min-height: 100vh; 8 | } 9 | 10 | .container { 11 | position: absolute; 12 | top: 50%; 13 | left: 50%; 14 | transform: translate(-50%, -50%); 15 | 16 | padding: 5%; 17 | } 18 | 19 | .header { 20 | margin: 0 0 100px 0; 21 | text-align: center; 22 | } 23 | .eq { 24 | margin: 20px; 25 | } 26 | 27 | input { 28 | font-size: 16px; 29 | width: 100%; 30 | outline: none; 31 | border: none; 32 | border-bottom: 1px solid #ca5303; 33 | background-color: transparent; 34 | } 35 | 36 | input:focus { 37 | border-bottom: 2px solid #ca5303; 38 | } 39 | 40 | .buttons { 41 | display: flex; 42 | justify-content: center; 43 | } 44 | .buttons button { 45 | width: 50%; 46 | height: 28px; 47 | border: none; 48 | border-radius: 5px; 49 | background-color: #ca5303ac; 50 | } 51 | 52 | .buttons button:hover { 53 | background-color: #ca5303; 54 | } 55 | 56 | textarea { 57 | resize: none; 58 | border: none; 59 | background-color: #ca530316; 60 | color: #ca5303; 61 | text-align: center; 62 | } 63 | -------------------------------------------------------------------------------- /02-TextToSpeech/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Text to Speech App 7 | 8 | 9 | 16 | 17 | 18 |
19 |

Text To Speech

20 |
21 |
22 | 23 | 24 |
25 |
26 | 27 |
28 | 29 |
30 |
31 | 32 | 37 |
38 |
39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /06-SnakeGame/css/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | 6 | body { 7 | display: flex; 8 | align-items: center; 9 | justify-content: center; 10 | min-height: 100vh; 11 | background: #e3f2fd; 12 | } 13 | 14 | .container { 15 | width: 65vmin; 16 | height: 70vmin; 17 | display: flex; 18 | overflow: hidden; 19 | flex-direction: column; 20 | justify-content: center; 21 | background: #293447; 22 | border-radius: 5px; 23 | box-shadow: 0 20px 40px #3457dc33; 24 | } 25 | 26 | .game-details { 27 | color: #b8c6dc; 28 | font-weight: 500; 29 | font-size: 1.2rem; 30 | padding: 20px 27px; 31 | display: flex; 32 | justify-content: space-between; 33 | } 34 | 35 | .game-board { 36 | height: 100%; 37 | width: 100%; 38 | display: grid; 39 | background: #212837; 40 | grid-template: repeat(30, 1fr) / repeat(30, 1fr); 41 | } 42 | 43 | .game-board .food { 44 | background: #ff003d; 45 | border-radius: 50%; 46 | } 47 | 48 | .game-board .head { 49 | background: #2ea225; 50 | margin: 0.5px; 51 | } 52 | 53 | .controller { 54 | display: none; 55 | justify-content: space-between; 56 | } 57 | 58 | .controller i { 59 | padding: 25px 0; 60 | text-align: center; 61 | font-size: 1.3rem; 62 | color: #b8c6dc; 63 | width: calc(100% / 4); 64 | cursor: pointer; 65 | border-right: 1px solid #171b26; 66 | } 67 | 68 | @media screen and (max-width: 600px) { 69 | .container { 70 | width: 90vmin; 71 | height: 115vmin; 72 | } 73 | 74 | .game-details { 75 | font-size: 1rem; 76 | padding: 15px 27px; 77 | } 78 | 79 | .controller { 80 | display: flex; 81 | } 82 | 83 | .controller i { 84 | padding: 15px 0; 85 | font-size: 1rem; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /04-QRCodeGenerator/css/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | padding: 0; 3 | margin: 0; 4 | } 5 | 6 | html, 7 | body { 8 | height: 100%; 9 | width: 100%; 10 | } 11 | 12 | .main-box { 13 | display: flex; 14 | width: 100%; 15 | height: 100vh; 16 | background-color: #edf7ff; 17 | } 18 | 19 | .box1 { 20 | width: 70%; 21 | display: flex; 22 | flex-direction: column; 23 | justify-content: center; 24 | 25 | margin: 3vw; 26 | padding-left: 3vw; 27 | } 28 | 29 | .heading h1 { 30 | font-weight: 500; 31 | } 32 | 33 | .box1 .link #link { 34 | outline: none; 35 | border: none; 36 | background: none; 37 | border-bottom: 1px solid #00288a; 38 | height: 2vw; 39 | width: 350px; 40 | color: #00278a9b; 41 | } 42 | .box1 .link #link:focus { 43 | border-bottom: 2px solid #00288a; 44 | } 45 | 46 | .heading h1::selection { 47 | background-color: #00278a9b; 48 | color: #fff; 49 | } 50 | 51 | .box2 { 52 | background-color: #00288a; 53 | width: 30%; 54 | border-radius: 10px; 55 | margin: 3vw; 56 | display: flex; 57 | flex-direction: column; 58 | align-items: center; 59 | justify-content: space-evenly; 60 | 61 | box-shadow: 0 0 25px #5b5c5d; 62 | } 63 | 64 | .qr-container { 65 | height: 275px; 66 | width: 275px; 67 | background-color: #ffffffde; 68 | border-radius: 5px; 69 | display: flex; 70 | align-items: center; 71 | justify-content: center; 72 | } 73 | #qr-code { 74 | cursor: pointer; 75 | } 76 | 77 | .size-input { 78 | width: 20vw; 79 | background-color: #edf7ff; 80 | box-shadow: 0 0 25px #5b5c5d; 81 | border-radius: 5px; 82 | } 83 | 84 | .sizes { 85 | background-color: #edf7ff; 86 | } 87 | 88 | .btn { 89 | text-decoration: none; 90 | background-color: #edf7ff; 91 | } 92 | .btn i { 93 | font-size: 18px; 94 | } 95 | 96 | .btn:hover { 97 | background-color: #ffffff9e; 98 | color: #fff; 99 | } 100 | 101 | /* ! this page is not optimize for other device ! */ 102 | -------------------------------------------------------------------------------- /02-TextToSpeech/js/script.js: -------------------------------------------------------------------------------- 1 | const txtArea = document.getElementById("txt-area"); 2 | const voiceList = document.getElementById("select-voice"); 3 | const speakPauseBtn = document.getElementById("speak-pause"); 4 | 5 | let speech = speechSynthesis; 6 | let isSpeaking = true; 7 | 8 | speech.addEventListener("voiceschanged", voices); //adding voices in html 9 | 10 | speakPauseBtn.addEventListener("click", e =>{ 11 | e.preventDefault(); 12 | if(txtArea.value !== "") { //if text in text-area 13 | if(!speech.speaking) { 14 | textTOspeech(txtArea.value); 15 | } 16 | if(txtArea.value.length > 0) { 17 | setInterval(() => { 18 | if(!speech.speaking && !isSpeaking) { 19 | isSpeaking = true; 20 | speakPauseBtn.innerText = "Speak"; 21 | } else {} 22 | },100); 23 | if(isSpeaking) { 24 | speech.resume(); 25 | isSpeaking = false; 26 | speakPauseBtn.innerText = "Pause"; 27 | } else { 28 | speech.pause(); 29 | isSpeaking = true; 30 | speakPauseBtn.innerText = "Resume"; 31 | } 32 | } 33 | } else { //if no text in text-area 34 | speakPauseBtn.innerText = "Speak"; 35 | } 36 | }); 37 | 38 | /*---- Getting Voices form API */ 39 | function voices() { 40 | for(let voice of speech.getVoices()) { 41 | let selected = voice.name === "Google US English" ? "selected" : " "; 42 | let option = ``; 45 | voiceList.insertAdjacentHTML('beforeend', option); 46 | } 47 | } 48 | /*---- ---*/ 49 | 50 | /*---- Converting text into voice ----*/ 51 | function textTOspeech(text) { 52 | let utterThis = new SpeechSynthesisUtterance(text); 53 | for(let voice of speech.getVoices()) { 54 | if(voice.name === voiceList.value) { 55 | utterThis.voice = voice 56 | } 57 | } 58 | speech.speak(utterThis); 59 | } 60 | /*---- ----*/ -------------------------------------------------------------------------------- /03-Translator/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Translator App 8 | 15 | 16 | 17 | 18 |
19 |
20 |
21 |
22 |
23 | 24 |
25 |
26 |
27 |
28 |
29 |
30 | 31 |
    32 |
  • 33 |
  • 34 |
35 |
36 |
37 | 38 |
    39 |
  • 40 |
  • 41 |
42 |
43 |
44 | 49 |
50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /05-TypingTest/css/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | padding: 0; 3 | margin: 0; 4 | } 5 | 6 | body { 7 | height: 100%; 8 | width: 100%; 9 | background-color: #121716; 10 | font-family: "Roboto Mono", "Roboto Mono", "Vazirmatn", monospace; 11 | } 12 | 13 | .container { 14 | padding: 2vw; 15 | width: 68vw; 16 | height: 40vw; 17 | border-radius: 1vw; 18 | position: absolute; 19 | top: 50%; 20 | left: 50%; 21 | transform: translate(-50%, -50%); 22 | } 23 | 24 | .box1, 25 | .box2 { 26 | height: inherit; 27 | } 28 | .info { 29 | display: flex; 30 | flex-direction: column; 31 | justify-content: center; 32 | align-items: center; 33 | color: #404846; 34 | padding: 3vw 0; 35 | } 36 | .info p { 37 | font-size: 15px; 38 | } 39 | #time { 40 | font-size: 40px; 41 | } 42 | .typing-area { 43 | padding: 3vw 0; 44 | } 45 | #quote { 46 | font-family: "Roboto Mono", "Roboto Mono", "Vazirmatn", monospace; 47 | color: gray; 48 | position: fixed; 49 | font-size: 22px; 50 | z-index: -10; 51 | } 52 | #type { 53 | outline: none; 54 | font-family: "Roboto Mono", "Roboto Mono", "Vazirmatn", monospace; 55 | caret-color: #1a6c4f; 56 | font-size: 22px; 57 | border: none; 58 | resize: none; 59 | width: 100%; 60 | height: 10vw; 61 | background-color: transparent; 62 | color: transparent; 63 | } 64 | .btn-body { 65 | display: flex; 66 | justify-content: center; 67 | padding: 3vw; 68 | } 69 | .btn-body .btn { 70 | font-size: 30px; 71 | color: #404846; 72 | cursor: pointer; 73 | } 74 | .btn-body .btn:hover { 75 | font-size: 31px; 76 | color: #707f7b; 77 | } 78 | 79 | .result-show { 80 | display: none; 81 | } 82 | .result { 83 | color: gray; 84 | padding: 25% 0; 85 | font-size: 25px; 86 | } 87 | .result h3 { 88 | text-align: center; 89 | } 90 | .result .wrapper { 91 | display: flex; 92 | justify-content: center; 93 | } 94 | .result .wrapper p { 95 | margin: 1vw 2vw; 96 | } 97 | 98 | .hr { 99 | border-bottom: 0.5px solid #707f7b; 100 | } 101 | 102 | .box3 { 103 | padding: 1vw 0; 104 | text-align: center; 105 | } 106 | .box3 a { 107 | text-decoration: none; 108 | margin: 0 2vw; 109 | color: #404846; 110 | } 111 | .box3 a:hover { 112 | color: #707f7b; 113 | border-bottom: 0.5px solid #707f7b; 114 | } 115 | 116 | .correct { 117 | color: #1a6c4f; 118 | } 119 | .wrong { 120 | color: #e81c4e; 121 | } 122 | 123 | /* not for mobile users so no need to make responsive for mobile device*/ 124 | -------------------------------------------------------------------------------- /05-TypingTest/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Typing Test 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 |
18 | 19 |
20 |

TIME

21 | 30 22 |
23 | 24 |
25 |
26 | 27 |
28 | 29 |
30 | 31 | 32 | 33 | 34 | 35 | 36 |
37 |
38 | 39 |
40 |
41 |

Result

42 |
43 |

Accuracy :

44 |

Speed :

45 |

Mistake : 0

46 | 47 |
48 |
49 | 50 |
51 |
52 |
53 | 54 | GitHub 55 | 56 | 57 | LinkedIn 58 | 59 |
60 | 61 |
62 | 63 | 64 | 65 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /08-2048Game/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 2048 Game 9 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 |
0
20 |
High Score 0
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | 41 |
42 | Game Over!! 43 | 44 |
45 | 46 |
47 | 48 | 49 | 50 | 51 |
52 |
53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /03-Translator/js/countries.js: -------------------------------------------------------------------------------- 1 | const countries = { 2 | "am-ET": "Amharic", 3 | "ar-SA": "Arabic", 4 | "be-BY": "Bielarus", 5 | "bem-ZM": "Bemba", 6 | "bi-VU": "Bislama", 7 | "bjs-BB": "Bajan", 8 | "bn-IN": "Bengali", 9 | "bo-CN": "Tibetan", 10 | "br-FR": "Breton", 11 | "bs-BA": "Bosnian", 12 | "ca-ES": "Catalan", 13 | "cop-EG": "Coptic", 14 | "cs-CZ": "Czech", 15 | "cy-GB": "Welsh", 16 | "da-DK": "Danish", 17 | "dz-BT": "Dzongkha", 18 | "de-DE": "German", 19 | "dv-MV": "Maldivian", 20 | "el-GR": "Greek", 21 | "en-GB": "English", 22 | "es-ES": "Spanish", 23 | "et-EE": "Estonian", 24 | "eu-ES": "Basque", 25 | "fa-IR": "Persian", 26 | "fi-FI": "Finnish", 27 | "fn-FNG": "Fanagalo", 28 | "fo-FO": "Faroese", 29 | "fr-FR": "French", 30 | "gl-ES": "Galician", 31 | "gu-IN": "Gujarati", 32 | "ha-NE": "Hausa", 33 | "he-IL": "Hebrew", 34 | "hi-IN": "Hindi", 35 | "hr-HR": "Croatian", 36 | "hu-HU": "Hungarian", 37 | "id-ID": "Indonesian", 38 | "is-IS": "Icelandic", 39 | "it-IT": "Italian", 40 | "ja-JP": "Japanese", 41 | "kk-KZ": "Kazakh", 42 | "km-KM": "Khmer", 43 | "kn-IN": "Kannada", 44 | "ko-KR": "Korean", 45 | "ku-TR": "Kurdish", 46 | "ky-KG": "Kyrgyz", 47 | "la-VA": "Latin", 48 | "lo-LA": "Lao", 49 | "lv-LV": "Latvian", 50 | "men-SL": "Mende", 51 | "mg-MG": "Malagasy", 52 | "mi-NZ": "Maori", 53 | "ms-MY": "Malay", 54 | "mt-MT": "Maltese", 55 | "my-MM": "Burmese", 56 | "ne-NP": "Nepali", 57 | "niu-NU": "Niuean", 58 | "nl-NL": "Dutch", 59 | "no-NO": "Norwegian", 60 | "ny-MW": "Nyanja", 61 | "ur-PK": "Pakistani", 62 | "pau-PW": "Palauan", 63 | "pa-IN": "Panjabi", 64 | "ps-PK": "Pashto", 65 | "pis-SB": "Pijin", 66 | "pl-PL": "Polish", 67 | "pt-PT": "Portuguese", 68 | "rn-BI": "Kirundi", 69 | "ro-RO": "Romanian", 70 | "ru-RU": "Russian", 71 | "sg-CF": "Sango", 72 | "si-LK": "Sinhala", 73 | "sk-SK": "Slovak", 74 | "sm-WS": "Samoan", 75 | "sn-ZW": "Shona", 76 | "so-SO": "Somali", 77 | "sq-AL": "Albanian", 78 | "sr-RS": "Serbian", 79 | "sv-SE": "Swedish", 80 | "sw-SZ": "Swahili", 81 | "ta-LK": "Tamil", 82 | "te-IN": "Telugu", 83 | "tet-TL": "Tetum", 84 | "tg-TJ": "Tajik", 85 | "th-TH": "Thai", 86 | "ti-TI": "Tigrinya", 87 | "tk-TM": "Turkmen", 88 | "tl-PH": "Tagalog", 89 | "tn-BW": "Tswana", 90 | "to-TO": "Tongan", 91 | "tr-TR": "Turkish", 92 | "uk-UA": "Ukrainian", 93 | "uz-UZ": "Uzbek", 94 | "vi-VN": "Vietnamese", 95 | "wo-SN": "Wolof", 96 | "xh-ZA": "Xhosa", 97 | "yi-YD": "Yiddish", 98 | "zu-ZA": "Zulu" 99 | } -------------------------------------------------------------------------------- /02-TextToSpeech/css/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800&display=swap'); 2 | 3 | *{ 4 | margin: 0; 5 | padding: 0; 6 | font-family: 'Poppins', sans-serif; 7 | font-family: 'Prata', serif; 8 | } 9 | 10 | body { 11 | height: 100vh; 12 | display: flex; 13 | justify-content: center; 14 | align-items: center; 15 | background-color: #908d8d47; 16 | } 17 | 18 | .main-box { 19 | width: 350px; 20 | height: 420px; 21 | padding: 50px; 22 | box-shadow: #00000033 0px 0px 22px, #0f5bce33 0px 2px 32px; 23 | border-radius: 10px; 24 | background-color: #fff; 25 | } 26 | 27 | .main-box h1 { 28 | text-align: center; 29 | font-size: 30px; 30 | font-weight: 400; 31 | } 32 | 33 | .form-body { 34 | margin: 20px 5px; 35 | } 36 | 37 | .form-con { 38 | display: flex; 39 | flex-direction: column; 40 | margin: 20px 0; 41 | } 42 | 43 | .form-con label { 44 | margin-bottom: 5px; 45 | font-size: 20px; 46 | } 47 | 48 | .form-con textarea { 49 | outline: none; 50 | resize: none; 51 | height: 150px; 52 | border: 1px solid black; 53 | border-radius: 5px; 54 | padding: 10px; 55 | font-size: 18px; 56 | } 57 | 58 | .form-con textarea::-webkit-scrollbar{ 59 | width: 0px; 60 | } 61 | 62 | .form-con select { 63 | outline: none; 64 | border: none; 65 | width: 100%; 66 | height: 100%; 67 | font-size: 15px; 68 | } 69 | .form-con .select-option { 70 | height: 30px; 71 | border-radius: 5px; 72 | border: 1px solid black; 73 | padding: 5px 10px; 74 | } 75 | 76 | .form-con .select-option select { 77 | outline: none; 78 | } 79 | 80 | .form-con select::-webkit-scrollbar{ 81 | width: 8px; 82 | } 83 | 84 | .form-con select::-webkit-scrollbar-track{ 85 | background: #fff; 86 | } 87 | 88 | .form-con select::-webkit-scrollbar-thumb{ 89 | background-color: #888; 90 | border-radius: 8px; 91 | border-right: 2px solid #fff; 92 | } 93 | 94 | .form-body button{ 95 | width: 100%; 96 | padding: 10px; 97 | transition: 0.3s ease; 98 | border-radius: 5px; 99 | border: none; 100 | background-color: #0a64da; 101 | color: #ffffff; 102 | cursor: pointer; 103 | transition: 0.3s ease; 104 | font-size: 20px; 105 | } 106 | 107 | .form-body button:hover { 108 | background-color: #0c4ea4; 109 | } 110 | 111 | .form-body .link { 112 | margin: 30px 0; 113 | text-align: center; 114 | } 115 | .form-body .link a { 116 | text-decoration: none; 117 | color: black; 118 | transition: 0.3s ease; 119 | } 120 | .form-body .link a i { 121 | margin-right: 2px; 122 | } 123 | .form-body .link :hover { 124 | text-decoration: underline; 125 | } 126 | -------------------------------------------------------------------------------- /01-PixelArtPalette/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Pixel Art Palette 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |

Rotate Device

23 |

OR

24 |

Go To Desktop Mode

25 | 26 | 27 |
28 |
29 |
30 | 31 |

Pixel Art Palette

32 | 33 |
34 | 35 | 36 | 25 37 |
38 | 39 |
40 | 41 | 42 | 25 43 |
44 | 45 | 46 | 47 |
48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | GitHub 60 | 61 |
62 | 63 |
64 |
65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /04-QRCodeGenerator/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | QR Code Generator 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |
19 |

Generate Your QR-Code

20 |
21 | 24 |
25 |
26 |
27 |
28 |
29 | 30 |
31 | 37 |
38 | 39 | 43 | 44 |
45 | 46 | 47 | 48 | 52 | 54 | 55 | 56 |
57 |
58 | 59 |
60 | 61 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /08-2048Game/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | height: 100vh; 3 | display: flex; 4 | flex-direction: column; 5 | justify-content: center; 6 | align-items: center; 7 | background-color: #161a30; 8 | overflow-y: hidden; 9 | } 10 | 11 | .container { 12 | } 13 | 14 | .gameScore { 15 | display: flex; 16 | justify-content: space-between; 17 | align-items: center; 18 | color: #f0ece5; 19 | } 20 | #gameScore { 21 | font-size: 65px; 22 | } 23 | 24 | .gameBoard { 25 | width: 320px; 26 | height: 320px; 27 | display: grid; 28 | grid-template-columns: repeat(4, 1fr); 29 | gap: 5px; 30 | } 31 | 32 | .gameBoard .cell { 33 | width: 77px; 34 | height: 77px; 35 | background-color: #31304d; 36 | display: flex; 37 | align-items: center; 38 | justify-content: center; 39 | font-size: 1.5em; 40 | color: #000; 41 | } 42 | 43 | .cell[data-value="2"] { 44 | background-color: #ffc0cb; 45 | } 46 | 47 | .cell[data-value="4"] { 48 | background-color: #add8e6; 49 | } 50 | 51 | .cell[data-value="8"] { 52 | background-color: #98fb98; 53 | } 54 | 55 | .cell[data-value="16"] { 56 | background-color: #ffd700; 57 | } 58 | 59 | .cell[data-value="32"] { 60 | background-color: #ffa07a; 61 | } 62 | 63 | .cell[data-value="64"] { 64 | background-color: #87ceeb; 65 | } 66 | 67 | .cell[data-value="128"] { 68 | background-color: #ffff00; 69 | } 70 | 71 | .cell[data-value="256"] { 72 | background-color: #40e0d0; 73 | } 74 | 75 | .cell[data-value="512"] { 76 | background-color: #ff69b4; 77 | } 78 | 79 | .cell[data-value="1024"] { 80 | background-color: #7b68ee; 81 | } 82 | 83 | .cell[data-value="2048"] { 84 | background-color: #ff6347; 85 | } 86 | 87 | .cell[data-value="4096"] { 88 | background-color: #a9a9a9; 89 | } 90 | 91 | .gameOver { 92 | display: none; 93 | position: absolute; 94 | top: 50%; 95 | left: 50%; 96 | padding: 20px; 97 | transform: translate(-50%, -50%); 98 | background-color: #000000ef; 99 | color: #fff; 100 | flex-direction: column; 101 | align-items: center; 102 | justify-content: center; 103 | 104 | box-shadow: 10px 10px 100px black; 105 | } 106 | #restart { 107 | width: 25px; 108 | height: 25px; 109 | font-size: 25px; 110 | color: #b6bbc4; 111 | } 112 | #restart:hover { 113 | color: #f0ece5; 114 | } 115 | 116 | .Controller { 117 | display: none; 118 | margin: 40px 0 0 0; 119 | justify-content: space-evenly; 120 | } 121 | 122 | .Controller i { 123 | font-size: 30px; 124 | margin: 0 20px; 125 | color: #b6bbc4; 126 | } 127 | 128 | .Controller i:hover { 129 | color: #f0ece5; 130 | } 131 | 132 | .game-cell[data-value] { 133 | transition: transform 0.5s, background-color 0.5s; 134 | } 135 | 136 | .new-cell { 137 | animation: appear 0.4s; 138 | } 139 | 140 | @keyframes appear { 141 | from { 142 | opacity: 0; 143 | transform: scale(0.5); 144 | } 145 | to { 146 | opacity: 1; 147 | transform: scale(1); 148 | } 149 | } 150 | 151 | @media (max-width: 1024px) { 152 | .Controller { 153 | display: flex; 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /07-UrlShorter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Tiny URL 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | 26 | 27 | 28 |
29 | 30 |
31 |
32 |

URL Shorter

33 |
34 |
35 | 36 |
37 |
38 | 39 |
40 |
41 | 42 |
43 |
44 | 45 |
46 |
47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /03-Translator/css/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800&display=swap'); 2 | 3 | * { 4 | margin: 0; 5 | padding: 0; 6 | font-family: 'Poppins', sans-serif; 7 | font-family: 'Prata', serif; 8 | } 9 | 10 | .box { 11 | box-shadow: #00000033 0px 0px 32px, #0f5bce5e 0px 2px 32px; 12 | border-radius: 10px; 13 | position: absolute; 14 | top: 50%; 15 | left: 50%; 16 | transform: translate(-50%, -50%); 17 | padding: 10px; 18 | } 19 | 20 | .lang-option-box { 21 | display: flex; 22 | justify-content: space-around; 23 | align-items: baseline; 24 | margin-bottom: 5px; 25 | } 26 | 27 | .lang-option-box .exchange { 28 | margin: 0 1em; 29 | } 30 | 31 | .lang-option-box div select { 32 | font-size: 20px; 33 | height: 30px; 34 | outline: none; 35 | border: none; 36 | border-radius: 5px; 37 | } 38 | 39 | .main-box { 40 | display: flex; 41 | justify-content: center; 42 | transition: all 0.3 ease; 43 | } 44 | 45 | .input-box, 46 | .output-box { 47 | border: 1px solid #c7c7c780; 48 | border-radius: 8px; 49 | padding: 10px; 50 | margin: 0 1em 1em; 51 | } 52 | 53 | .output-box { 54 | border: none; 55 | background-color: #c7c7c748; 56 | } 57 | 58 | .input-box textarea, 59 | .output-box textarea { 60 | outline: none; 61 | border: none; 62 | resize: none; 63 | background-color: #ffffff00; 64 | height: 100px; 65 | width: 20em; 66 | font-size: 20px; 67 | } 68 | 69 | .options { 70 | display: flex; 71 | list-style-type: none; 72 | } 73 | .input-box .options { 74 | justify-content: flex-start; 75 | } 76 | .output-box .options { 77 | justify-content: flex-end; 78 | } 79 | 80 | .all-icon { 81 | cursor: pointer; 82 | padding: 10px; 83 | border-radius: 50%; 84 | transition: background-color 0.5s ease; 85 | transition: 0.3s ease; 86 | } 87 | .all-icon:hover { 88 | background-color: #c7c7c7a2; 89 | } 90 | 91 | .link { 92 | margin: 30px 0; 93 | text-align: center; 94 | } 95 | .link-a { 96 | text-decoration: none; 97 | color: black; 98 | transition: 0.3s ease; 99 | } 100 | .link a i { 101 | margin-right: 4px; 102 | } 103 | .link:hover { 104 | text-decoration: underline; 105 | } 106 | 107 | /* ---- Responsive ---- */ 108 | 109 | @media (max-width: 930px) { 110 | .main-box { 111 | flex-wrap: wrap; 112 | } 113 | } 114 | 115 | @media (max-width: 480px) { 116 | .input-box textarea, 117 | .output-box textarea { 118 | width: 15em; 119 | } 120 | } 121 | 122 | @media (max-width: 412px) { 123 | .box { 124 | width: 85%; 125 | padding-left: 5px; 126 | padding-right: 5px; 127 | } 128 | .input-box textarea, 129 | .output-box textarea { 130 | width: 15em; 131 | } 132 | .lang-option-box div select { 133 | font-size: 15px; 134 | width: 5em; 135 | height: 30px; 136 | } 137 | } 138 | 139 | /* ---- Dark mode ---- */ 140 | 141 | .body-dark { 142 | background-color: black; 143 | } 144 | 145 | .select-dark { 146 | background-color: black; 147 | color: white; 148 | } 149 | 150 | .textarea-dark { 151 | color: white; 152 | } 153 | 154 | .all-icon-dark { 155 | color: white; 156 | transition: 0.3s ease; 157 | } 158 | 159 | .link-dark { 160 | color: white; 161 | transition: 0.3s ease; 162 | } 163 | .link-dark:hover { 164 | text-decoration: underline; 165 | } 166 | -------------------------------------------------------------------------------- /06-SnakeGame/js/script.js: -------------------------------------------------------------------------------- 1 | // const snakeGame = () => { 2 | 3 | let gameOver = false; 4 | let snakeX = 5, snakeY = 5; //snake position 5 | let foodX, foodY; //food position 6 | let velocityX = 0, velocityY = 0; 7 | let snakeBody = []; 8 | let score = 0; 9 | let highScore = localStorage.getItem("high-score") || 0; // Get high score 10 | let setIntervalId; 11 | 12 | const highScoreElement = document.querySelector(".high-score"); 13 | highScoreElement.innerText = `High Score: ${highScore}`; 14 | 15 | 16 | const startGame = () => { 17 | if (gameOver) return handleGameOver(); 18 | 19 | let html = `
`;//food position 20 | 21 | // snake eats the food 22 | if (snakeX === foodX && snakeY === foodY) { 23 | updateFoodPosition(); 24 | snakeBody.push([foodY, foodX]); //increase snake size 25 | score++; 26 | highScore = score >= highScore ? score : highScore; //calculate high score 27 | 28 | //set the score and high-score 29 | localStorage.setItem("high-score", highScore); 30 | document.querySelector(".score").innerText = `Score: ${score}`; 31 | highScoreElement.innerText = `High Score: ${highScore}`; 32 | console.log(snakeBody); 33 | } 34 | 35 | // Update Snake Head 36 | snakeX += velocityX; 37 | snakeY += velocityY; 38 | 39 | //snake moves 40 | for (let i = snakeBody.length - 1; i > 0; i--) { 41 | snakeBody[i] = snakeBody[i - 1]; 42 | } 43 | snakeBody[0] = [snakeX, snakeY]; 44 | 45 | // is snake crash? 46 | if (snakeX <= 0 || snakeX > 30 || snakeY <= 0 || snakeY > 30) { 47 | return gameOver = true; 48 | } 49 | 50 | // increase snake body 51 | for (let i = 0; i < snakeBody.length; i++) { 52 | html += `
`; 53 | 54 | // snake head hit to his body 55 | if (i !== 0 && snakeBody[0][1] === snakeBody[i][1] && snakeBody[0][0] === snakeBody[i][0]) { 56 | gameOver = true; 57 | } 58 | } 59 | document.querySelector(".game-board").innerHTML = html; 60 | }; 61 | 62 | //game over 63 | const handleGameOver = () => { 64 | clearInterval(setIntervalId); 65 | alert("Game Over!"); 66 | location.reload(); 67 | } 68 | 69 | // generate food in random position 70 | const updateFoodPosition = () => { 71 | const generateRandomPosition = () => { 72 | return Math.floor(Math.random() * 30) + 1; 73 | } 74 | foodX = generateRandomPosition(); 75 | foodY = generateRandomPosition(); 76 | } 77 | 78 | // Change snake direction 79 | const changeDirection = e => { 80 | if (e.key === "ArrowUp" && velocityY != 1) { 81 | velocityX = 0; 82 | velocityY = -1; 83 | } else if (e.key === "ArrowDown" && velocityY != -1) { 84 | velocityX = 0; 85 | velocityY = 1; 86 | } else if (e.key === "ArrowLeft" && velocityX != 1) { 87 | velocityX = -1; 88 | velocityY = 0; 89 | } else if (e.key === "ArrowRight" && velocityX != -1) { 90 | velocityX = 1; 91 | velocityY = 0; 92 | } 93 | } 94 | 95 | // Change Direction on each key click 96 | document.querySelectorAll(".controller i") 97 | .forEach(button => button.addEventListener("click", () => 98 | changeDirection({ key: button.dataset.key }))); 99 | 100 | updateFoodPosition(); 101 | setIntervalId = setInterval(startGame, 100); 102 | document.addEventListener("keyup", changeDirection); 103 | // }; 104 | // snakeGame(); 105 | -------------------------------------------------------------------------------- /04-QRCodeGenerator/js/script.js: -------------------------------------------------------------------------------- 1 | const pageLoadingAnimation = () => { 2 | 3 | gsap.from(".heading h1", { 4 | x: 100, 5 | opacity: 0, 6 | delay: 0.2, 7 | stagger: 0.8 8 | }); 9 | gsap.from(".box1 .link #link", { 10 | x: 100, 11 | opacity: 0, 12 | delay: 0.8, 13 | stagger: 0.5 14 | }); 15 | 16 | gsap.from(".box2", { 17 | opacity: 0, 18 | delay: 0.2, 19 | }); 20 | 21 | gsap.from(".ld", { 22 | opacity: 0, 23 | delay: 0.5, 24 | }); 25 | gsap.from("#qr-code", { 26 | opacity: 0, 27 | delay: 0.8, 28 | }); 29 | }; 30 | pageLoadingAnimation(); 31 | 32 | const qrCodeGenerator = () => { 33 | 34 | const defaultUrl = "https://github.com/alfaArghya"; 35 | // const defaultUrl = "I Love U"; 36 | let color1 = "#fff", color2 = "#000"; 37 | let text = defaultUrl, size = 200; 38 | 39 | /* ---- change -> color of QR || ---- */ 40 | // document.querySelector("#col-inp1") 41 | // .addEventListener("input", (e) => { 42 | // color1 = e.target.value; 43 | // generateQRCode(); 44 | // }); 45 | 46 | // document.querySelector("#col-inp2") 47 | // .addEventListener("input", (e) => { 48 | // color2 = e.target.value; 49 | // generateQRCode(); 50 | // }); 51 | 52 | /* !! important - scanner can not scan to much colorful QR !! */ 53 | /* ---- ----*/ 54 | 55 | /* ---- change -> size of QR ---- */ 56 | document.querySelector(".sizes"). 57 | addEventListener("change", (e) => { 58 | size = e.target.value; 59 | generateQRCode(); 60 | }); 61 | /* ---- ---- */ 62 | 63 | /* ---- change -> QR according to text & link ---- */ 64 | document.querySelector("#link"). 65 | addEventListener("input", (e) => { 66 | const value = e.target.value; 67 | text = value; 68 | if (!value) { 69 | text = defaultUrl; 70 | } 71 | generateQRCode(); 72 | }); 73 | /* ---- ---- */ 74 | 75 | document.querySelector("#share-btn") 76 | .addEventListener("click", async () => { 77 | setTimeout(async () => { 78 | try { 79 | const base64url = await resolveDataUrl(); 80 | const blob = await (await fetch(base64url)).blob(); 81 | const file = new File([blob], "QRCode.png", { 82 | type: blob.type, 83 | }); 84 | await navigator.share({ 85 | files: [file], 86 | title: text, 87 | }); 88 | } catch (err) { 89 | alert("Browser doesn't support share option") 90 | } 91 | }) 92 | }, 100); 93 | 94 | 95 | /* ---- generate the qr code ---- */ 96 | const generateQRCode = async () => { 97 | document.querySelector("#qr-code").innerHTML = ""; 98 | new QRCode("qr-code", { 99 | text, 100 | height: size, 101 | width: size, 102 | // colorLight: color1, 103 | // colorDark: color2, 104 | }); 105 | document.querySelector("#download-btn") 106 | .href = await resolveDataUrl(); 107 | }; 108 | generateQRCode(); 109 | /* ---- ---- */ 110 | 111 | const resolveDataUrl = () => { 112 | return new Promise((resolve, reject) => { 113 | setTimeout(() => { 114 | const img = document.querySelector("#qr-code img"); 115 | if (img.currentSrc) { 116 | resolve(img.currentSrc); 117 | return; 118 | } 119 | }, 50); 120 | }); 121 | }; 122 | 123 | }; 124 | qrCodeGenerator(); 125 | -------------------------------------------------------------------------------- /01-PixelArtPalette/js/main.js: -------------------------------------------------------------------------------- 1 | let gridHeight = document.getElementById("height-rng"); 2 | let heightValue = document.getElementById("height-value"); 3 | let gridWidth = document.getElementById("width-rng"); 4 | let widthValue = document.getElementById("width-value"); 5 | let createBtn = document.getElementById("create-grid"); 6 | let resetBtn = document.getElementById("reset-grid"); 7 | let colorChoice = document.getElementById("color-choice"); 8 | let paintBtn = document.getElementById("paint-btn"); 9 | let eraserBtn = document.getElementById("eraser-btn"); 10 | let grid = document.querySelector(".grid-box"); 11 | 12 | let events = { 13 | mouse: { 14 | down: "mousedown", 15 | up: "mouseup", 16 | move: "mousemove" 17 | }, 18 | touch: { 19 | down: "touchstart", 20 | up: "touchend", 21 | move: "touchmove" 22 | }, 23 | }; 24 | 25 | let deviceType = ""; 26 | 27 | let draw = false; 28 | let erase = false; 29 | 30 | window.onload = () => { 31 | gridHeight.value = 25; 32 | gridWidth.value = 25; 33 | }; 34 | 35 | gridWidth.addEventListener("input", () => { 36 | widthValue.innerHTML = gridWidth.value < 9 ? `0${gridWidth.value}` : gridWidth.value; 37 | }); 38 | 39 | gridHeight.addEventListener("input", () => { 40 | heightValue.innerHTML = gridHeight.value < 9 ? `0${gridHeight.value}` : gridHeight.value; 41 | }); 42 | 43 | resetBtn.addEventListener("click", () => { 44 | grid.innerHTML = ""; 45 | }); 46 | 47 | paintBtn.addEventListener("click", () => { 48 | erase = false; 49 | }); 50 | 51 | eraserBtn.addEventListener("click", () => { 52 | erase = true; 53 | }); 54 | 55 | const isTouchDevice = () => { 56 | try { 57 | document.createEvent("TouchEvent"); 58 | deviceType = "touch"; 59 | return true; 60 | } catch (e) { 61 | deviceType = "mouse"; 62 | return false; 63 | } 64 | }; 65 | 66 | isTouchDevice(); 67 | 68 | createBtn.addEventListener("click", () => { 69 | grid.innerHTML = ""; 70 | let count = 0; 71 | for (let i = 0; i < gridHeight.value; i++) { 72 | count += 2; 73 | let row = document.createElement("div"); 74 | row.classList.add("gridRow"); 75 | 76 | for (let j = 0; j < gridWidth.value; j++) { 77 | count += 2; 78 | let col = document.createElement("div"); 79 | col.classList.add("gridCol"); 80 | col.setAttribute("id", `gridCol${count}`); 81 | 82 | col.addEventListener(events[deviceType].down, () => { 83 | draw = true; 84 | if (erase) { 85 | col.style.backgroundColor = "transparent"; 86 | } else { 87 | col.style.backgroundColor = colorChoice.value; 88 | } 89 | }); 90 | 91 | col.addEventListener(events[deviceType].move, (e) => { 92 | let elementId = document.elementFromPoint( 93 | !isTouchDevice() ? e.clientX : e.touches[0].clientX, 94 | !isTouchDevice() ? e.clientY : e.touches[0].clientY, 95 | ).id; 96 | checker(elementId); 97 | }); 98 | 99 | col.addEventListener(events[deviceType].up, () => { 100 | draw = false; 101 | }); 102 | 103 | row.appendChild(col); 104 | 105 | } 106 | 107 | grid.appendChild(row); 108 | 109 | } 110 | }); 111 | 112 | function checker(elementId) { 113 | let gridColumns = document.querySelectorAll(".gridCol"); 114 | gridColumns.forEach((element) => { 115 | if (elementId == element.id) { 116 | if (draw && !erase) { 117 | element.style.backgroundColor = colorChoice.value; 118 | } else if (draw && erase) { 119 | element.style.backgroundColor = "transparent"; 120 | } 121 | } 122 | }); 123 | } 124 | -------------------------------------------------------------------------------- /01-PixelArtPalette/css/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | padding: 0; 3 | margin: 0; 4 | } 5 | 6 | body { 7 | background-color: #fafafa; 8 | } 9 | 10 | .mob-device { 11 | display: none; 12 | } 13 | 14 | .main-box { 15 | display: flex; 16 | justify-content: space-evenly; 17 | height: 100vh; 18 | margin: 0 50px; 19 | align-items: center; 20 | } 21 | 22 | .options { 23 | display: flex; 24 | flex-direction: column; 25 | border: 2px solid none; 26 | box-shadow: #00000033 0px 0px 2px, #0f5bce33 0px 2px 32px; 27 | padding: 3em; 28 | position: absolute; 29 | left: 5%; 30 | 31 | } 32 | 33 | .options h1 { 34 | text-align: center; 35 | } 36 | 37 | .option-item { 38 | margin: 10px 0; 39 | } 40 | 41 | .slider { 42 | display: flex; 43 | align-content: baseline; 44 | } 45 | 46 | .slider-all { 47 | margin: 0 10px; 48 | } 49 | 50 | label { 51 | display: block; 52 | font-size: 18px; 53 | } 54 | 55 | span { 56 | position: relative; 57 | } 58 | 59 | button { 60 | font-size: 16px; 61 | align-self: center; 62 | background-color: #2684ff; 63 | border-radius: 5px; 64 | color: rgb(255, 255, 255); 65 | width: 10rem; 66 | height: 2.5rem; 67 | transition: background-color 0.2s ease-out 0s; 68 | border: none; 69 | cursor: pointer; 70 | } 71 | 72 | button:hover { 73 | background-color: #1361c7; 74 | } 75 | 76 | .option-item { 77 | margin: 10px 0; 78 | } 79 | 80 | .color-box { 81 | text-align: center; 82 | margin: 10px 0; 83 | } 84 | 85 | input[type="color"] { 86 | -webkit-appearance: none; 87 | -moz-appearance: none; 88 | appearance: none; 89 | width: 8rem; 90 | height: 3rem; 91 | border-color: transparent; 92 | cursor: pointer; 93 | align-self: center; 94 | 95 | padding: 0; 96 | border: none; 97 | overflow: hidden; 98 | } 99 | 100 | input[type="text"]:focus { 101 | outline: none; 102 | } 103 | 104 | .git { 105 | text-align: center; 106 | position: relative; 107 | bottom: -2em; 108 | } 109 | 110 | .git a { 111 | text-decoration: none; 112 | color: black; 113 | cursor: pointer; 114 | } 115 | 116 | .git a:hover { 117 | color: #1361c7; 118 | } 119 | 120 | .grid-box { 121 | border: 2px solid none; 122 | box-shadow: #00000033 0px 0px 2px, #0f5bce33 0px 2px 32px; 123 | position: absolute; 124 | left: 43%; 125 | } 126 | 127 | .gridRow { 128 | display: flex; 129 | } 130 | 131 | .gridCol { 132 | height: 0.6em; 133 | width: 0.6em; 134 | border: 1px solid #d0d0d0; 135 | } 136 | 137 | @media only screen and (max-width: 1058px) { 138 | .gridCol { 139 | height: 0.45em; 140 | width: 0.45em; 141 | } 142 | 143 | .grid-box { 144 | left: 50%; 145 | } 146 | } 147 | @media only screen and (max-width: 390px) { 148 | .mob-device { 149 | display: block; 150 | position: absolute; 151 | top: 50%; 152 | left: 50%; 153 | transform: translate(-50%,-50%); 154 | } 155 | 156 | .mob-device span { 157 | font-weight: 700; 158 | } 159 | .mob-device p { 160 | text-align: center; 161 | font-weight: 700; 162 | } 163 | 164 | .main-box { 165 | display: none; 166 | } 167 | } 168 | @media only screen and (max-width: 896px) and (max-height: 414px) { 169 | body { 170 | overflow:auto; 171 | } 172 | .options { 173 | left: 2%;; 174 | } 175 | .options h1 { 176 | font-size: 30px; 177 | } 178 | label { 179 | font-size: 16px; 180 | } 181 | button { 182 | font-size: 14px; 183 | width: 8rem; 184 | height: 2rem; 185 | } 186 | input[type="color"] { 187 | width: 6rem; 188 | height: 2.5rem; 189 | } 190 | .color-box { 191 | margin: 1px 0; 192 | } 193 | .option-item { 194 | margin: 4px 0; 195 | 196 | } 197 | } -------------------------------------------------------------------------------- /03-Translator/js/script.js: -------------------------------------------------------------------------------- 1 | let input = document.getElementById("user-input"); 2 | let output = document.getElementById("translate-output"); 3 | let exchange = document.querySelector(".exchange i"); 4 | let langOption = document.querySelectorAll(".lang-option-box div select"); 5 | let speakBtn = document.querySelectorAll(".options li .speakBtn"); 6 | let copyBtn = document.querySelectorAll(".options li .copyBtn"); 7 | let darkBtn = document.querySelector(".dark-mode"); 8 | let lightBtn = document.querySelector(".light-mode"); 9 | 10 | /* adding language options into select tag */ 11 | langOption.forEach((tag, id) => { 12 | for (let countryCode in countries) { 13 | let selected = 14 | id == 0 15 | ? countryCode == "en-GB" 16 | ? "selected" 17 | : "" 18 | : countryCode == "hi-IN" 19 | ? "selected" 20 | : ""; 21 | let option = ``; 24 | tag.insertAdjacentHTML("beforeend", option); 25 | } 26 | }); 27 | /*---- ----*/ 28 | 29 | /*---- Translate the input text ----*/ 30 | input.addEventListener("keyup", () => { 31 | if (!input.value) { 32 | output.value = ""; 33 | } else { 34 | let text = input.value; 35 | let translateFrom = langOption[0].value; 36 | let translateTo = langOption[1].value; 37 | if (!text) { 38 | return; 39 | } 40 | 41 | output.setAttribute("placeholder", "Translating...."); 42 | let api = `https://api.mymemory.translated.net/get?q=${text}&langpair=${translateFrom}|${translateTo}`; 43 | fetch(api) 44 | .then((res) => res.json()) 45 | .then((data) => { 46 | output.value = data.responseData.translatedText; 47 | data.matches.forEach((data) => { 48 | if (data.id === 0) { 49 | output.value = data.translation; 50 | } 51 | }); 52 | output.setAttribute("placeholder", "Translate"); 53 | }); 54 | } 55 | }); 56 | /*---- ----*/ 57 | 58 | /*---- Speak Button ----*/ 59 | speakBtn.forEach(btn => { 60 | btn.addEventListener("click", () => { 61 | if(!input.value || !output.value){ 62 | return; 63 | } 64 | let utterance; 65 | if(btn.id == "inp-speak") { 66 | utterance = new SpeechSynthesisUtterance(input.value); 67 | utterance.lang = langOption[0].value; 68 | } else if(btn.id == "opt-speak") { 69 | utterance = new SpeechSynthesisUtterance(output.value); 70 | utterance.lang = langOption[1].value; 71 | } 72 | speechSynthesis.speak(utterance); 73 | }); 74 | }); 75 | /*---- ----*/ 76 | 77 | /*---- Copy Button ----*/ 78 | copyBtn.forEach(btn => { 79 | btn.addEventListener("click", () => { 80 | if(!input.value || !output.value){ 81 | return; 82 | } 83 | if(btn.id == "inp-copy") { 84 | // console.log(input.value); 85 | navigator.clipboard.writeText(input.value); 86 | } else if(btn.id == "opt-copy") { 87 | // console.log(output.value); 88 | navigator.clipboard.writeText(output.value); 89 | } 90 | }); 91 | }); 92 | /*---- ----*/ 93 | 94 | /*---- Exchange Button ----*/ 95 | exchange.addEventListener("click", () => { 96 | let tempText = input.value; 97 | input.value = output.value; 98 | output.value = tempText; 99 | 100 | let tempLang = langOption[0].value; 101 | langOption[0].value = langOption[1].value; 102 | langOption[1].value = tempLang; 103 | }); 104 | /*---- ----*/ 105 | 106 | /*---- Dark Mode & Light Mode ----*/ 107 | darkBtn.addEventListener("click", () => { 108 | document.querySelector("body").classList.add("body-dark"); 109 | langOption[0].classList.add("select-dark"); 110 | langOption[1].classList.add("select-dark"); 111 | input.classList.add("textarea-dark"); 112 | output.classList.add("textarea-dark"); 113 | document.querySelector(".link a").classList.add("link-dark"); 114 | document.querySelectorAll(".all-icon").forEach(btn => { 115 | btn.classList.add("all-icon-dark"); 116 | }); 117 | }); 118 | 119 | lightBtn.addEventListener("click", () => { 120 | document.querySelector("body").classList.remove("body-dark"); 121 | langOption[0].classList.remove("select-dark"); 122 | langOption[1].classList.remove("select-dark"); 123 | input.classList.remove("textarea-dark"); 124 | output.classList.remove("textarea-dark"); 125 | document.querySelector(".link a").classList.remove("link-dark"); 126 | document.querySelectorAll(".all-icon").forEach(btn => { 127 | btn.classList.remove("all-icon-dark"); 128 | }); 129 | }) 130 | /*---- ----*/ 131 | -------------------------------------------------------------------------------- /08-2048Game/js/script.js: -------------------------------------------------------------------------------- 1 | const gameLogic = () => { 2 | 3 | const gameScore = document.querySelector("#gameScore"); 4 | const gameHighScore = document.querySelector("#gameHighScore"); 5 | const gameOver = document.querySelector(".gameOver"); 6 | 7 | let score = 0; 8 | let highScore = localStorage.getItem('game-highScore') || 0; //getting highScore from local storage 9 | let game = []; 10 | let size = 4; 11 | 12 | gameHighScore.textContent = highScore; 13 | 14 | //score update 15 | const scoreUpdate = (value) => { 16 | score += value; 17 | gameScore.textContent = score; 18 | 19 | // highScore update 20 | if (score > highScore) { 21 | highScore = score; 22 | gameHighScore.textContent = highScore; 23 | localStorage.setItem('game-highScore', highScore); 24 | } 25 | }; 26 | 27 | //start the game 28 | const initGame = () => { 29 | //fill array with 0 30 | game = [...Array(size)].map(element => Array(size).fill(0)); 31 | 32 | randomGenerate(); 33 | randomGenerate(); 34 | renderGame(); 35 | }; 36 | 37 | //restart the game 38 | const restart = () => { 39 | score = 0; 40 | gameScore.textContent = '0'; 41 | gameOver.style.display = 'none'; 42 | initGame(); 43 | }; 44 | 45 | 46 | //generate random cells on game board 47 | const randomGenerate = () => { 48 | const emptyPosition = []; 49 | //get positions where 0 present 50 | for (let i = 0; i < size; i++) { 51 | for (let j = 0; j < size; j++) { 52 | if (game[i][j] === 0) { 53 | emptyPosition.push({ x: i, y: j }); 54 | } 55 | } 56 | } 57 | 58 | //place random value between 2 and 4 59 | if (emptyPosition.length > 0) { 60 | const randomCell = emptyPosition[Math.floor(Math.random() * emptyPosition.length)]; 61 | // console.log(randomCell); 62 | game[randomCell.x][randomCell.y] = Math.random() < 0.9 ? 2 : 4; 63 | // console.log(game[randomCell.x][randomCell.y]); 64 | const cell = document.querySelector(`[data-row="${randomCell.x}"][data-column="${randomCell.y}"]`); 65 | cell.classList.add("new-cell"); 66 | } 67 | 68 | }; 69 | 70 | //generate or update game 71 | const renderGame = () => { 72 | for (let i = 0; i < size; i++) { 73 | for (let j = 0; j < size; j++) { 74 | 75 | const cell = document.querySelector(`[data-row="${i}"][data-column="${j}"]`); 76 | 77 | //get the values 78 | const oldValue = cell.dataset.value; 79 | const newValue = game[i][j]; 80 | 81 | //render the cell 82 | if (newValue !== 0) { 83 | cell.dataset.value = newValue; 84 | cell.textContent = newValue; 85 | 86 | if (newValue !== parseInt(oldValue) && !cell.classList.contains('new-cell')) { 87 | cell.classList.add('merged-cell'); 88 | } 89 | } else { 90 | cell.textContent = ''; 91 | delete cell.dataset.value; 92 | cell.classList.remove('merged-cell', 'new-cell'); 93 | } 94 | } 95 | } 96 | 97 | setTimeout(() => { 98 | const cells = document.querySelectorAll('.game-cell'); 99 | cells.forEach(cell => { 100 | cell.classList.remove('merged-cell', 'new-cell') 101 | }); 102 | }, 300); 103 | }; 104 | 105 | 106 | //transform the game 107 | const transform = (line, moveDirection) => { 108 | 109 | let newLine = line.filter((cell) => cell !== 0); 110 | if (!moveDirection) { 111 | newLine.reverse(); 112 | } 113 | 114 | for (let i = 0; i < newLine.length - 1; i++) { 115 | if (newLine[i] === newLine[i + 1]) { 116 | newLine[i] *= 2; 117 | scoreUpdate(newLine[i]); 118 | newLine.splice(i + 1, 1); 119 | } 120 | } 121 | while (newLine.length < size) { 122 | newLine.push(0); 123 | } 124 | if (!moveDirection) { 125 | newLine.reverse(); 126 | } 127 | return newLine; 128 | 129 | }; 130 | 131 | 132 | //move the column & row 133 | const move = (direction) => { 134 | let isChanged = false; 135 | 136 | if (direction === 'ArrowUp' || direction === 'ArrowDown') { 137 | for (let j = 0; j < size; j++) { 138 | const column = [...Array(size)].map((_, i) => game[i][j]); 139 | const newColumn = transform(column, direction === 'ArrowUp'); 140 | for (let i = 0; i < size; i++) { 141 | if (game[i][j] !== newColumn[i]) { 142 | isChanged = true; 143 | game[i][j] = newColumn[i]; 144 | } 145 | } 146 | } 147 | } else if (direction === 'ArrowLeft' || direction === 'ArrowRight') { 148 | for (let i = 0; i < size; i++) { 149 | const row = game[i]; 150 | const newRow = transform(row, direction === 'ArrowLeft'); 151 | if (row.join(',') !== newRow.join(',')) { 152 | isChanged = true; 153 | game[i] = newRow; 154 | } 155 | } 156 | } 157 | 158 | if (isChanged) { 159 | randomGenerate(); 160 | renderGame(); 161 | } 162 | 163 | }; 164 | 165 | 166 | //checking... is game over or not?? 167 | const isGameOver = () => { 168 | for (let i = 0; i < size; i++) { 169 | for (let j = 0; j < size; j++) { 170 | if (game[i][j] === 0) { 171 | return; 172 | } 173 | if (j < size - 1 && game[i][j] === game[i][j + 1]) { 174 | return; 175 | } 176 | if (i < size - 1 && board[i][j] === board[i + 1][j]) { 177 | return; 178 | } 179 | } 180 | } 181 | gameOver.style.display = 'flex'; 182 | } 183 | 184 | //game controls 185 | document.addEventListener('keydown', event => { 186 | if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(event.key)) { 187 | move(event.key); 188 | } 189 | }); 190 | 191 | //game buttons 192 | document.querySelector("#up-arrow").addEventListener("click", () => { 193 | document.addEventListener("click", () => { 194 | move('ArrowUp'); 195 | }) 196 | }); 197 | document.querySelector("#down-arrow").addEventListener("click", () => { 198 | document.addEventListener("click", () => { 199 | move('ArrowDown'); 200 | }) 201 | }); 202 | document.querySelector("#right-arrow").addEventListener("click", () => { 203 | document.addEventListener("click", () => { 204 | move('ArrowRight'); 205 | }) 206 | }); 207 | document.querySelector("#left-arrow").addEventListener("click", () => { 208 | document.addEventListener("click", () => { 209 | move('ArrowLeft'); 210 | }) 211 | }); 212 | 213 | 214 | //restart btn 215 | document.getElementById('restart').addEventListener('click', restart); 216 | 217 | 218 | initGame(); 219 | }; 220 | 221 | gameLogic(); -------------------------------------------------------------------------------- /05-TypingTest/js/script.js: -------------------------------------------------------------------------------- 1 | /* ---- Page animation Code ---- */ 2 | const pageLoadingAnimation = () => { 3 | 4 | gsap.from(".info", { 5 | y: -50, 6 | opacity: 0, 7 | delay: 0.5, 8 | }); 9 | gsap.from(".typing-area", { 10 | opacity: 0, 11 | delay: 1, 12 | }); 13 | gsap.from(".btn-body", { 14 | y: -50, 15 | opacity: 0, 16 | delay: 0.5, 17 | }); 18 | gsap.from(".hr", { 19 | opacity: 0, 20 | delay: 0.2, 21 | }); 22 | gsap.from(".box3", { 23 | y: -20, 24 | opacity: 0, 25 | delay: 0.5, 26 | }); 27 | }; 28 | pageLoadingAnimation(); 29 | /* ---- ---- */ 30 | 31 | /* ---- Typing test Code ---- */ 32 | let quote = ""; 33 | let mistake = 0; 34 | let time = 30; 35 | let timer = ""; 36 | let startingPoint = 1; 37 | const defaultQuote = [ 38 | `Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatem recusandae dicta ipsa autem dignissimos corporis repudiandae esse deserunt distinctio quo?`, 39 | `Whether the FOMO makes your anxiety go through the roof, or you just struggle with keeping up with your daily to-do list, the world’s greatest minds have already been there.`, 40 | `This famous line holds a very true sentiment. Within “the grind” culture today, we tend to think that whatever doesn’t make us money or is an investment in the future is a waste of time. Instead, we should realize that so long as we enjoy an activity, the amount of time spent on it doesn’t matter.`, 41 | `Enjoy your Netflix binge if it will ease the stress of the day; go window shopping for hours; nap out your afternoon. Enjoy your downtime guilt-free.`, 42 | `Learning how to manage our time is a skill that requires constant work. We tend to lose a lot of time on unnecessary things – a minute here, ten minutes there, only to end up with an entire wasted day on meaningless tasks.`, 43 | `We more commonly hear “This too shall pass”, as a way of comforting ourselves during difficult times. But, what we often forget is that those moments are when we truly grow, harden, and evolve.`, 44 | `Simply waiting for a rough period to pass, we lose out on the opportunity to learn from the experience and become stronger. See what lessons you can learn from such a time.`, 45 | `Too many times we’ve heard stories of people regretting not taking a chance on their dreams because they weren’t good enough yet, or weren’t confident enough, or lacked the resources or support. When we keep promising ourselves that “someday” we’ll realize our passion, we effectively lose time.`, 46 | `In this quote from “The Merry Wives of Windsor”, Shakespeare alluded to the benefits of doing something earlier rather than missing an opportunity. It is so easy to put off things like writing up an email, checking a job listing, getting a medical check-up, and so on. We get lost in other things until it becomes too late`, 47 | `Have you noticed how each generation tends to reminisce about their past, claiming it was much better in their day? As it turns out, it is a very human thing to do — our brains tend to embellish the good memories. The times haven’t changed, only our perception of them.`, 48 | `It’s a very common saying that there are no age limits to anything in life. Morgan Freeman landed his first big role at 52, and Winston Churchill became Prime Minister at 66!`, 49 | `Let go of any fears or embarrassment that you are too young or too old to take up a career endeavor. The only mistake you can make is waiting so long, you give up in the end.`, 50 | `The biggest favor we can do ourselves is to accept the passage of time, both when good and bad things happen. The sooner we face our troubles, the sooner they’ll be over.`, 51 | `This is a thought from a fictional character, but an important one nonetheless. As he was about to leave his newfound family to rejoin the one that didn’t want him, Harry wanted to make the last good moments last as long as possible. With this thought, J.K. Rowling pointed out that, no matter how much we wish to stop time when hardship is on the horizon, we can’t go against it.` 52 | ]; 53 | 54 | const userInput = document.getElementById("type"); 55 | const stopBtn = document.getElementById("stop-test"); 56 | const reStartBtn = document.getElementById("restart-test"); 57 | 58 | //window loading 59 | window.onload = () => { 60 | userInput.value = ""; 61 | stopBtn.style.display = "none"; 62 | generateRandomQuote(); 63 | } 64 | 65 | /* ---- Generate Random Quote ---- */ 66 | const generateRandomQuote = async () => { 67 | const quoteHTML = document.getElementById("quote"); 68 | try { 69 | const response = await fetch("https://api.quotable.io/random?minLength=300&maxLength=400"); 70 | let data = await response.json(); 71 | quote = data.content; 72 | // quoteHTML.innerHTML = quote; 73 | let arr = quote.split("").map((val) => { 74 | return "" + val + ""; 75 | }); 76 | quoteHTML.innerHTML = arr.join(""); 77 | } catch (error) { 78 | console.log(error); 79 | quote = defaultQuote[Math.floor(Math.random() * 14)]; 80 | 81 | let arr = quote.split("").map((val) => { 82 | return "" + val + ""; 83 | }); 84 | 85 | quoteHTML.innerHTML = arr.join(""); 86 | } 87 | 88 | }; 89 | /* ---- typing test start ---- */ 90 | const startTest = () => { 91 | mistake = 0; 92 | timer = ""; 93 | startingPoint = 1; 94 | timeReduce(); 95 | reStartBtn.style.display = "none"; 96 | stopBtn.style.display = "block"; 97 | }; 98 | /* ---- ---- */ 99 | 100 | /* ---- user is typing ---- */ 101 | userInput.addEventListener("input", () => { 102 | 103 | let quoteChars = Array.from(document.querySelectorAll(".quote-char")); 104 | 105 | let userInputChars = userInput.value.split(""); 106 | 107 | //condition for start timer 108 | if (startingPoint == 1 && userInputChars.length == 1) { 109 | startTest(); 110 | } 111 | startingPoint++; 112 | 113 | //check user-input char & quote char 114 | quoteChars.forEach((char, idx) => { 115 | //if it's correct make it green 116 | if (char.innerText == userInputChars[idx]) { 117 | char.classList.add("correct"); 118 | //if no input no color 119 | } else if (userInputChars[idx] == null) { 120 | if (char.classList.contains("correct")) { 121 | char.classList.remove("correct"); 122 | } else { 123 | char.classList.remove("wrong"); 124 | } 125 | //wrong input make it red 126 | } else { 127 | if (!char.classList.contains("wrong")) { 128 | mistake++; 129 | char.classList.add("wrong"); 130 | } 131 | document.getElementById("mistake").innerText = mistake; 132 | } 133 | 134 | let check = quoteChars.every((element) => { 135 | return element.classList.contains("correct"); 136 | }); 137 | 138 | 139 | if (check) { 140 | result(); 141 | } 142 | 143 | }); 144 | 145 | }); 146 | /* ---- ---- */ 147 | 148 | /* ---- timer ---- */ 149 | const updateTime = () => { 150 | if (time == 0) { 151 | result(); 152 | } else { 153 | document.getElementById("time").innerText = --time; 154 | } 155 | } 156 | 157 | const timeReduce = () => { 158 | time = 30; 159 | timer = setInterval(updateTime, 1000); 160 | } 161 | /* ---- ---- */ 162 | 163 | /* ---- result of typing test ---- */ 164 | const result = () => { 165 | document.querySelector(".result-hide").style.display = "none"; 166 | document.querySelector(".result-show").style.display = "block"; 167 | clearInterval(timer); 168 | stopBtn.style.display = "none" 169 | userInput.disabled = true; 170 | let timeTaken = 1; 171 | if (time != 0) { 172 | timeTaken = (30 - time) / 100; 173 | } 174 | document.querySelector("#accuracy").innerText = Math.round(((userInput.value.length - mistake) / userInput.value.length) * 100) + " %"; 175 | 176 | document.querySelector("#speed").innerText = (userInput.value.length / 5 / timeTaken).toFixed(2) + " wpm"; 177 | } 178 | /* ---- ---- */ 179 | /*---- ---- */ --------------------------------------------------------------------------------