├── .gitattributes ├── README.md ├── day#01-random-color-generator ├── .vscode │ └── settings.json ├── index.html ├── index.js ├── project-demo │ └── demo.png └── style.css ├── day#02-rock-papper-scissor-game ├── index.html ├── index.js ├── project-demo │ └── demo.png └── style.css └── day#3-todo-app ├── .vscode └── settings.json ├── README.md ├── index.html ├── project-ss └── preview.png ├── script.js └── style.css /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 50 Days of JavaScript 2 | 3 | Sona Code's Web Design Projects 4 | 5 | ## Description 6 | 7 | Welcome to "50 Days of JavaScript" project series! This series is designed to take your JavaScript skills to the next level with a new project every day for 50 days. Each project is built using modern JavaScript syntax and techniques, and is carefully crafted to challenge you and help you improve your skills. 8 | 9 | From building games like rock paper scissors and tic tac toe, to creating dynamic user interfaces and web applications, this series has something for everyone. With each project, you'll learn new concepts and techniques, and gain valuable experience working with JavaScript, HTML, and CSS. 10 | 11 | Whether you're just starting out with JavaScript or you're a seasoned pro looking to expand your skills, "50 Days of JavaScript" is the perfect way to challenge yourself and improve your abilities. So why wait? Join us on this exciting journey and take your JavaScript skills to the next level today! 12 | 13 | ## Demo 14 | 15 | You can view live demos of each project by visiting the following links: 16 | 17 | - [Random Color Generator](https://dinil-thilakarathne.github.io/50days-of-js/day%2301-random-color-generator/index.html) 18 | ![](/day%2301-random-color-generator/project-demo/demo.png) 19 | - [Rock Paper Scissor Game](https://dinil-thilakarathne.github.io/50days-of-js/day%2302-rock-papper-scissor-game/index.html) 20 | ![](/day%2302-rock-papper-scissor-game//project-demo/demo.png) 21 | - [Todo app](https://dinil-thilakarathne.github.io/50days-of-js/day%233-todo-app/index.html) 22 | ![](/day%233-todo-app//project-ss/preview.png) 23 | 24 | 25 | 26 | ## Concepts Used 27 | 28 | The following concepts and technologies were used in the creation of these projects: 29 | 30 | - Responsive design 31 | - CSS animations 32 | - Flexbox 33 | - Grid 34 | - jQuery 35 | 36 | ## Social Media Links 37 | 38 | Follow Sona Code on social media for more web design inspiration and project updates: 39 | 40 | - [Twitter](https://twitter.com/sona_code) 41 | - [Instagram](https://www.instagram.com/sona_code/) 42 | - [GitHub](https://github.com/sonacode) 43 | 44 | 45 | -------------------------------------------------------------------------------- /day#01-random-color-generator/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "liveServer.settings.port": 5501 3 | } -------------------------------------------------------------------------------- /day#01-random-color-generator/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Color Picker 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 |
19 |

Color Generator

20 |
21 | 22 |
23 |
24 |
25 |
26 |

Hex :

27 |
28 |
29 |

Rgb :

30 |
31 |
32 |
33 | 34 | 41 |
42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /day#01-random-color-generator/index.js: -------------------------------------------------------------------------------- 1 | const colors = [0 , 1 ,2 , 3, 4, 5, 6, 7, 8, 9, "A", "B", "C", "D" , "E", "F"]; 2 | const generateBtn = document.getElementById("color-generate-btn"); 3 | const colorBox =document.getElementById("colorBox"); 4 | const hexValue = document.getElementById("color-hex-value"); 5 | const rgbValue = document.getElementById("color-rgb-value"); 6 | 7 | 8 | // generate random color 9 | generateBtn.addEventListener("click" , () =>{ 10 | let color = "#"; 11 | for(let i =0 ; i < 6 ; i++){ 12 | color += colors[getRandomValue()]; 13 | } 14 | // change box bg color 15 | colorBox.style.backgroundColor = color; 16 | 17 | // display color values 18 | hexValue.textContent = color; 19 | rgbValue.textContent = hexToRgb(color); 20 | }) 21 | 22 | // generate random number 23 | getRandomValue = () =>{ 24 | return Math.floor(Math.random()*colors.length); 25 | } 26 | 27 | // hex to rgb convert 28 | hexToRgb = (hex) => { 29 | const r = parseInt(hex.substring(1, 3), 16); 30 | const g = parseInt(hex.substring(3, 5), 16); 31 | const b = parseInt(hex.substring(5, 7), 16); 32 | 33 | return "rgb(" + r + ", " + g + ", " + b + ")"; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /day#01-random-color-generator/project-demo/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dinil-Thilakarathne/50days-of-js/b93125e0b8643565cf64b9f732f3cb0189a6797f/day#01-random-color-generator/project-demo/demo.png -------------------------------------------------------------------------------- /day#01-random-color-generator/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | fonts 3 | */ 4 | @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;700&display=swap'); 5 | 6 | /* 7 | Global variables 8 | */ 9 | :root{ 10 | /* colors */ 11 | --card-bg-color:#00CCFF ; 12 | --card-shadow:2.3px 2.3px 2.2px rgba(0, 0, 0, 0.037),5.2px 5.2px 5.1px rgba(0, 0, 0, 0.053),9.3px 9.3px 9.3px rgba(0, 0, 0, 0.065),16.2px 16.2px 16.2px rgba(0, 0, 0, 0.077),30.7px 30.7px 30.6px rgba(0, 0, 0, 0.093),100px 100px 80px rgba(0, 0, 0, 0.13); 13 | --btn-bg-color:#00CCFF; 14 | --btn-border-color:#ff0066; 15 | --btn-hover-bg-color:#ff0066; 16 | 17 | /* fonts */ 18 | --main-font:'Poppins', sans-seri; 19 | --fc-main-text:#000; 20 | --fc-btn-text:#000; 21 | --fc-btn-hover-text:#fff; 22 | --fc-body-span-text:#ff0066; 23 | --fs-header-text:24px; 24 | --fs-body-text:16px; 25 | --fs-btn-text:16px; 26 | --fw-header-text:700; 27 | --fw-body-text:400; 28 | --fw-btn-text:700; 29 | 30 | /* transition */ 31 | --btn-transition:all 1s ease; 32 | } 33 | 34 | *{ 35 | margin: 0; 36 | padding: 0; 37 | box-sizing: border-box; 38 | } 39 | 40 | body{ 41 | min-height: 100vh; 42 | width: 100%; 43 | display: flex; 44 | align-items: center; 45 | justify-content: center; 46 | font-family: var(--main-font); 47 | } 48 | 49 | /* container */ 50 | .container{ 51 | height: 500px; 52 | width: 600px; 53 | background-color: var(--card-bg-color); 54 | display: flex; 55 | flex-direction: column; 56 | align-items: center; 57 | justify-content: space-between; 58 | padding: 40px; 59 | border-radius: 20px; 60 | box-shadow: var(--card-shadow); 61 | } 62 | /* container header */ 63 | .container-header{ 64 | height: 10%; 65 | width: 100%; 66 | text-align: center; 67 | font-size: var(--fs-header-text); 68 | font-weight: var(--fw-header-text); 69 | color: var(--fc-main-text); 70 | } 71 | 72 | /* container body */ 73 | .container-body{ 74 | height: 80%; 75 | width: 100%; 76 | display: flex; 77 | align-items: center; 78 | justify-content: space-between; 79 | 80 | } 81 | 82 | /* color box */ 83 | .color-box{ 84 | height: 250px; 85 | width: 250px; 86 | background-color: antiquewhite; 87 | border-radius: 20px; 88 | } 89 | 90 | /* color info */ 91 | .color-info{ 92 | height: 100px; 93 | width: calc(100% - 270px ); 94 | display: flex; 95 | flex-direction: column; 96 | align-items: flex-start; 97 | justify-content: space-around; 98 | font-size: var(--fs-body-text); 99 | font-weight: var(--fw-body-text); 100 | color: var(--fc-main-text); 101 | } 102 | .color-info .color-value{ 103 | width: 100%; 104 | background-color: #fff; 105 | border-radius: 10px; 106 | margin: 10px 0; 107 | padding: 10px 10px; 108 | } 109 | .color-info span{ 110 | color: var(--fc-body-span-text); 111 | } 112 | 113 | /* container footer */ 114 | .container-footer{ 115 | height: 10%; 116 | width: 100%; 117 | display: inline-flex; 118 | align-items: center; 119 | justify-content: center; 120 | } 121 | 122 | .container-footer button{ 123 | /* width: 100%; */ 124 | border: 2px solid var(--btn-border-color); 125 | border-radius: 10px; 126 | padding: 10px 15px ; 127 | background-color: var(--btn-bg-color); 128 | font-size: var(--fs-btn-text); 129 | font-weight: var(--fw-btn-text); 130 | color: var(--fc-btn-text); 131 | cursor: pointer; 132 | } 133 | .container-footer button:hover{ 134 | background-color: var(--btn-hover-bg-color); 135 | color: var(--fc-btn-hover-text); 136 | transition: var(--btn-transition); 137 | } 138 | 139 | /* responsive design */ 140 | @media screen and (max-width:768px) { 141 | :root{ 142 | /* fonts */ 143 | --fs-header-text:16px; 144 | --fs-body-text:12px; 145 | --fs-btn-text:16px; 146 | } 147 | .container{ 148 | height: 600px; 149 | width: 350px; 150 | padding: 20px 40px; 151 | } 152 | .container-body{ 153 | flex-direction: column; 154 | justify-content: space-around; 155 | } 156 | .color-box, 157 | .color-info{ 158 | width: 100%; 159 | } 160 | .color-info{ 161 | align-items: center; 162 | } 163 | 164 | } 165 | -------------------------------------------------------------------------------- /day#02-rock-papper-scissor-game/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Rock papper scissor game 8 | 9 | 10 | 11 |
12 |
13 |

Rock paper scissor game

14 |
15 |
16 |
17 |

Choose your move :

18 |
19 |
20 | 23 | 26 | 29 |
30 | 31 |
32 | 43 |
44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /day#02-rock-papper-scissor-game/index.js: -------------------------------------------------------------------------------- 1 | const buttons = document.querySelectorAll("button"); 2 | const resultText = document.getElementById("resultText"); 3 | const playerScoreText = document.getElementById("playerScore") 4 | const computerScoreText = document.getElementById("computerScore") 5 | 6 | let playerScore = 0; 7 | let computerScore = 0; 8 | 9 | 10 | buttons.forEach((button) => { 11 | button.addEventListener("click", () => { 12 | const result = playRound(button.id, computerPlay()); 13 | resultText.textContent = result; 14 | playerScoreText.textContent = playerScore; 15 | computerScoreText.textContent = computerScore; 16 | }); 17 | }); 18 | 19 | computerPlay = () => { 20 | const choices = ["rock" , "paper" , "scissor"]; 21 | return choices[Math.floor(Math.random()*choices.length)]; 22 | } 23 | 24 | playRound = (playerChoice, computerChoice) => { 25 | if(playerChoice === computerChoice){ 26 | return "Game tie"; 27 | }else if ( 28 | (playerChoice === "rock" && computerChoice ==="scissor") || 29 | (playerChoice === "scissor" && computerChoice ==="paper") || 30 | (playerChoice === "paper" && computerChoice ==="rock") 31 | ){ 32 | playerScore ++; 33 | console.log(`player score ${playerScore}`); 34 | return `you win ! ${playerChoice} beats ${computerChoice}`; 35 | }else{ 36 | computerScore ++; 37 | console.log(`computer score ${computerScore}`); 38 | return `you lost ! ${computerChoice} beats ${playerChoice}`; 39 | } 40 | } -------------------------------------------------------------------------------- /day#02-rock-papper-scissor-game/project-demo/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dinil-Thilakarathne/50days-of-js/b93125e0b8643565cf64b9f732f3cb0189a6797f/day#02-rock-papper-scissor-game/project-demo/demo.png -------------------------------------------------------------------------------- /day#02-rock-papper-scissor-game/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | Global font family 3 | */ 4 | @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;700&display=swap'); 5 | /* 6 | Global variables 7 | */ 8 | 9 | :root { 10 | --bg-color: #1E1E1E ; 11 | --primary-color: #ECECEC ; 12 | --rock-color: #ff0000; 13 | --paper-color: #2196f3; 14 | --scissor-color: #4caf50; 15 | --container-shadow:0.5px 0.3px 1.1px rgba(0, 0, 0, 0.061),1px 0.6px 2.9px rgba(0, 0, 0, 0.087),2px 1.2px 5.8px rgba(0, 0, 0, 0.096),5.6px 3.4px 12px rgba(0, 0, 0, 0.109),10px 15px 33px rgba(0, 0, 0, 0.16); 16 | } 17 | 18 | *{ 19 | margin: 0; 20 | padding: 0; 21 | box-sizing: border-box; 22 | } 23 | 24 | body{ 25 | min-height: 100vh; 26 | width: 100%; 27 | display: flex; 28 | align-items: center; 29 | justify-content: center; 30 | font-family: "poppins"; 31 | } 32 | 33 | /* container */ 34 | .container{ 35 | height: 400px; 36 | width: 500px; 37 | background-color: var(--primary-color); 38 | padding: 40px 20px; 39 | display: flex; 40 | flex-direction: column; 41 | align-items: center; 42 | justify-content: space-around; 43 | border-radius: 20px; 44 | box-shadow: var(--container-shadow); 45 | } 46 | 47 | .container-body{ 48 | height: 40%; 49 | width: 100%; 50 | display: flex; 51 | flex-direction: column; 52 | align-items: center; 53 | justify-content: space-around; 54 | } 55 | .container-body .btn-group{ 56 | height: 60%; 57 | width: 60%; 58 | display: flex; 59 | align-items: center; 60 | justify-content: space-around; 61 | } 62 | .btn-group .btn{ 63 | padding: 20px; 64 | border: none; 65 | border-radius: 10px; 66 | font-size: 2rem; 67 | cursor: pointer; 68 | } 69 | .btn:nth-child(1){ 70 | background-color: var(--rock-color); 71 | } 72 | .btn:nth-child(2){ 73 | background-color: var(--paper-color); 74 | } 75 | .btn:nth-child(3){ 76 | background-color: var(--scissor-color); 77 | } 78 | 79 | .container-footer .mark-section{ 80 | height: 10%; 81 | width: 100%; 82 | text-align: center; 83 | font-size: 1.2rem; 84 | } 85 | #resultText, 86 | .mark-section p span{ 87 | font-weight: bold; 88 | } 89 | -------------------------------------------------------------------------------- /day#3-todo-app/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "liveServer.settings.port": 5501 3 | } -------------------------------------------------------------------------------- /day#3-todo-app/README.md: -------------------------------------------------------------------------------- 1 | # How to create Todo app using HTML , CSS & JavaScript 2 | 3 | ## Watch Full video on Youtube 4 | - 5 | 6 | # Demo 7 | ## live Demo : 8 | - [demo](https://dinil-thilakarathne.github.io/50days-of-js/day%233-todo-app/index.html) 9 | 10 | ## Project Preview 11 | 12 | ![](project-ss/preview.png) 13 | 14 | 15 | 16 | ## Keep with touch 17 | 18 | - YouTube : [@sonacode]("https://www.youtube.com/@sonacode/videos") 19 | - GitHub : [Dinil Thilakarathne]("https://github.com/Dinil-Thilakarathne/") 20 | - Instagram : [@sona_code]("https://www.instagram.com/sona_code/") 21 | -------------------------------------------------------------------------------- /day#3-todo-app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 |

Todo App

20 | 21 | 22 |
23 | 24 | 27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
36 | 37 | -------------------------------------------------------------------------------- /day#3-todo-app/project-ss/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dinil-Thilakarathne/50days-of-js/b93125e0b8643565cf64b9f732f3cb0189a6797f/day#3-todo-app/project-ss/preview.png -------------------------------------------------------------------------------- /day#3-todo-app/script.js: -------------------------------------------------------------------------------- 1 | // Array to store tasks 2 | let tasks = []; 3 | 4 | // Function to add a new task 5 | function addTask() { 6 | const taskInput = document.getElementById('taskInput'); 7 | const taskName = taskInput.value; 8 | 9 | console.log(taskName); 10 | 11 | if(taskName.trim() !== ''){ 12 | const task = { 13 | id : Date.now(), 14 | name : taskName, 15 | completed : false 16 | }; 17 | 18 | tasks.push(task); 19 | renderTasks(); 20 | taskInput.value = ''; 21 | } 22 | } 23 | // Function to delete a task 24 | function deleteTask(id){ 25 | tasks = tasks.filter(task => task.id !== id); 26 | renderTasks(); 27 | } 28 | 29 | // Function to mark a task as completed 30 | function markCompeleted(id){ 31 | tasks = tasks.map(task => { 32 | if(task.id === id){ 33 | task.completed = !task.completed; 34 | } 35 | return task; 36 | }); 37 | renderTasks(); 38 | updateCompleteTask(id); 39 | 40 | 41 | } 42 | function updateCompleteTask(id){ 43 | const taskElement = document.getElementById(id); 44 | if(taskElement){ 45 | const task = tasks.find(task => task.id === id); 46 | if(task.completed){ 47 | taskElement.classList.add('completed'); 48 | }else{ 49 | taskElement.classList.remove('completed'); 50 | } 51 | } 52 | } 53 | 54 | // Function to render tasks on the page 55 | function renderTasks() { 56 | const taskList = document.getElementById('taskList'); 57 | taskList.innerHTML = ''; 58 | 59 | tasks.forEach(task => { 60 | // create new list item 61 | const listItem = document.createElement('li'); 62 | listItem.setAttribute('id', task.id); 63 | 64 | // create task name span 65 | const taskName = document.createElement('span'); 66 | taskName.innerHTML = task.name; 67 | 68 | // create task compelete button 69 | const completeButton = document.createElement('i'); 70 | completeButton.classList.add('bx','bx-check','compelete-btn'); 71 | completeButton.addEventListener('click' , () => markCompeleted(task.id)) 72 | 73 | // create task delete button 74 | const deleteButton = document.createElement('i'); 75 | deleteButton.classList.add('bx','bxs-trash','delete-btn'); 76 | deleteButton.addEventListener('click' , () => deleteTask(task.id)) 77 | 78 | // add all elements into list 79 | listItem.appendChild(taskName); 80 | listItem.appendChild(completeButton); 81 | listItem.appendChild(deleteButton); 82 | taskList.appendChild(listItem); 83 | 84 | }); 85 | } 86 | 87 | // Initial rendering of tasks 88 | renderTasks() 89 | -------------------------------------------------------------------------------- /day#3-todo-app/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | fonts 3 | */ 4 | @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;700&display=swap'); 5 | 6 | /* 7 | global variables 8 | */ 9 | :root{ 10 | /* colors */ 11 | --clr-primary-btn: #007bff ; 12 | --clr-compelete-btn: #28a745; 13 | --clr-delete-btn: #f44336 ; 14 | --clr-btn-text:#fff; 15 | --clr-bg-1:#fc466b; 16 | --clr-bg-2:#3f5efb; 17 | --clr-app-bg:#fff; 18 | --clr-item-bg:#f3f6fc; 19 | --clr-item-hover-bg:#dbe7ff; 20 | 21 | /* typography */ 22 | 23 | /* font sizes */ 24 | --fs-large:2rem; 25 | --fs-regular:1.2rem; 26 | --fs-body:14px; 27 | } 28 | /* 29 | base 30 | */ 31 | *{ 32 | margin: 0; 33 | padding: 0; 34 | box-sizing: border-box; 35 | } 36 | body{ 37 | min-height: 100vh; 38 | width: 100%; 39 | display: flex; 40 | align-items: center; 41 | justify-content: center; 42 | font-family: 'poppins'; 43 | background: linear-gradient(to right,var(--clr-bg-1),var(--clr-bg-2)); 44 | } 45 | .btn{ 46 | padding: .5rem .75rem; 47 | border: none; 48 | border-radius: .5rem; 49 | cursor: pointer; 50 | color: var(--clr-btn-text); 51 | font-weight: bold; 52 | } 53 | 54 | /* app */ 55 | .todo-app{ 56 | min-width: 80%; 57 | max-width: 800px; 58 | margin: 40px; 59 | padding: .5rem; 60 | background-color: var(--clr-app-bg); 61 | border-radius: 1rem; 62 | } 63 | .todo-app h1{ 64 | text-align: center; 65 | } 66 | .input-group{ 67 | display: flex; 68 | align-items: center; 69 | justify-content: center; 70 | column-gap: 1rem; 71 | } 72 | input[type='text']{ 73 | padding: .5rem .75rem; 74 | border-radius: .5rem; 75 | } 76 | 77 | .add-task-btn{ 78 | background-color: var(--clr-primary-btn); 79 | } 80 | 81 | #taskList{ 82 | margin-top: 1rem; 83 | width: 100%; 84 | display: flex; 85 | flex-direction: column; 86 | } 87 | li{ 88 | list-style-type: none; 89 | display: inline-flex; 90 | align-items: center; 91 | justify-content: flex-start; 92 | max-width: 560px; 93 | margin: .25rem auto; 94 | padding-inline: .25rem; 95 | position: relative; 96 | background-color: var(--clr-item-bg); 97 | border-radius: .5rem; 98 | } 99 | li:hover{ 100 | background-color: var(--clr-item-hover-bg); 101 | } 102 | li * { 103 | margin: .5rem; 104 | } 105 | 106 | .compelete-btn{ 107 | color: var(--clr-compelete-btn); 108 | cursor: pointer; 109 | } 110 | .delete-btn{ 111 | color: var(--clr-delete-btn); 112 | cursor: pointer; 113 | } 114 | 115 | .completed{ 116 | text-decoration: line-through; 117 | color: #007bff; 118 | } 119 | .completed .delete-btn{ 120 | pointer-events: none; 121 | } 122 | 123 | --------------------------------------------------------------------------------