├── 01-Fundamentals-Part-1 ├── final │ ├── index.html │ └── script.js └── starter │ └── index.html ├── 02-Fundamentals-Part-2 ├── final │ ├── index.html │ └── script.js └── starter │ ├── index.html │ └── script.js ├── 03-Developer-Skills ├── final │ ├── .prettierrc │ ├── index.html │ └── script.js └── starter │ ├── index.html │ └── script.js ├── 04-HTML-CSS └── final │ ├── index.html │ └── style.css ├── 05-Guess-My-Number ├── final │ ├── .prettierrc │ ├── index.html │ ├── script.js │ └── style.css └── starter │ ├── .prettierrc │ ├── index.html │ ├── script.js │ └── style.css ├── 06-Modal ├── final │ ├── .prettierrc │ ├── index.html │ ├── script.js │ └── style.css └── starter │ ├── .prettierrc │ ├── index.html │ ├── script.js │ └── style.css ├── 07-Pig-Game ├── final │ ├── .prettierrc │ ├── dice-1.png │ ├── dice-2.png │ ├── dice-3.png │ ├── dice-4.png │ ├── dice-5.png │ ├── dice-6.png │ ├── index.html │ ├── pig-game-flowchart.png │ ├── script.js │ └── style.css └── starter │ ├── .prettierrc │ ├── dice-1.png │ ├── dice-2.png │ ├── dice-3.png │ ├── dice-4.png │ ├── dice-5.png │ ├── dice-6.png │ ├── index.html │ ├── pig-game-flowchart.png │ ├── script.js │ └── style.css ├── 08-Behind-the-Scenes ├── final │ ├── .prettierrc │ ├── index.html │ └── script.js └── starter │ ├── .prettierrc │ ├── index.html │ └── script.js ├── 09-Data-Structures-Operators ├── final │ ├── .prettierrc │ ├── index.html │ └── script.js └── starter │ ├── .prettierrc │ ├── index.html │ └── script.js ├── 10-Functions ├── final │ ├── .prettierrc │ ├── index.html │ └── script.js └── starter │ ├── .prettierrc │ ├── index.html │ └── script.js ├── 11-Arrays-Bankist ├── final │ ├── .prettierrc │ ├── Bankist-flowchart.png │ ├── icon.png │ ├── index.html │ ├── logo.png │ ├── script.js │ └── style.css └── starter │ ├── .prettierrc │ ├── Bankist-flowchart.png │ ├── icon.png │ ├── index.html │ ├── logo.png │ ├── script.js │ └── style.css ├── 12-Numbers-Dates-Timers-Bankist ├── final │ ├── .prettierrc │ ├── Bankist-flowchart.png │ ├── icon.png │ ├── index.html │ ├── logo.png │ ├── script.js │ └── style.css └── starter │ ├── .prettierrc │ ├── Bankist-flowchart.png │ ├── icon.png │ ├── index.html │ ├── logo.png │ ├── script.js │ └── style.css ├── 13-Advanced-DOM-Bankist ├── final │ ├── .prettierrc │ ├── img │ │ ├── card-lazy.jpg │ │ ├── card.jpg │ │ ├── digital-lazy.jpg │ │ ├── digital.jpg │ │ ├── grow-lazy.jpg │ │ ├── grow.jpg │ │ ├── hero.png │ │ ├── icon.png │ │ ├── icons.svg │ │ ├── img-1.jpg │ │ ├── img-2.jpg │ │ ├── img-3.jpg │ │ ├── img-4.jpg │ │ ├── logo.png │ │ ├── user-1.jpg │ │ ├── user-2.jpg │ │ └── user-3.jpg │ ├── index.html │ ├── script.js │ └── style.css └── starter │ ├── .prettierrc │ ├── img │ ├── card-lazy.jpg │ ├── card.jpg │ ├── digital-lazy.jpg │ ├── digital.jpg │ ├── grow-lazy.jpg │ ├── grow.jpg │ ├── hero.png │ ├── icon.png │ ├── icons.svg │ ├── img-1.jpg │ ├── img-2.jpg │ ├── img-3.jpg │ ├── img-4.jpg │ ├── logo.png │ ├── user-1.jpg │ ├── user-2.jpg │ └── user-3.jpg │ ├── index.html │ ├── script.js │ └── style.css ├── 14-OOP ├── final │ ├── .prettierrc │ ├── index.html │ └── script.js └── starter │ ├── .prettierrc │ ├── index.html │ └── script.js ├── 15-Mapty ├── final │ ├── .prettierrc │ ├── Mapty-architecture-final.png │ ├── Mapty-architecture-part-1.png │ ├── Mapty-flowchart.png │ ├── icon.png │ ├── index.html │ ├── logo.png │ ├── other.js │ ├── script.js │ └── style.css └── starter │ ├── .prettierrc │ ├── Mapty-architecture-final.png │ ├── Mapty-architecture-part-1.png │ ├── Mapty-flowchart.png │ ├── icon.png │ ├── index.html │ ├── logo.png │ ├── script.js │ └── style.css ├── 16-Asynchronous ├── final │ ├── .prettierrc │ ├── img │ │ ├── img-1.jpg │ │ ├── img-2.jpg │ │ └── img-3.jpg │ ├── index.html │ ├── script.js │ └── style.css └── starter │ ├── .prettierrc │ ├── img │ ├── img-1.jpg │ ├── img-2.jpg │ └── img-3.jpg │ ├── index.html │ ├── script.js │ └── style.css ├── 17-Modern-JS-Modules-Tooling ├── final │ ├── .prettierrc │ ├── clean.js │ ├── dist │ │ ├── index.html │ │ ├── index.js │ │ ├── index.js.map │ │ ├── script.0b6e4fd3.js │ │ ├── script.0b6e4fd3.js.map │ │ ├── script.75da7f30.js │ │ └── script.75da7f30.js.map │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── script.js │ └── shoppingCart.js └── starter │ ├── .prettierrc │ ├── clean.js │ ├── index.html │ └── script.js ├── 18-forkify ├── final │ ├── .gitignore │ ├── .prettierrc │ ├── README.md │ ├── index.html │ ├── package-lock.json │ ├── package.json │ └── src │ │ ├── img │ │ ├── favicon.png │ │ ├── icons.svg │ │ └── logo.png │ │ ├── js │ │ ├── config.js │ │ ├── controller.js │ │ ├── helpers.js │ │ ├── model.js │ │ └── views │ │ │ ├── View.js │ │ │ ├── addRecipeView.js │ │ │ ├── bookmarksView.js │ │ │ ├── paginationView.js │ │ │ ├── previewView.js │ │ │ ├── recipeView.js │ │ │ ├── resultsView.js │ │ │ └── searchView.js │ │ └── sass │ │ ├── _base.scss │ │ ├── _components.scss │ │ ├── _header.scss │ │ ├── _preview.scss │ │ ├── _recipe.scss │ │ ├── _searchResults.scss │ │ ├── _upload.scss │ │ └── main.scss └── starter │ ├── .prettierrc │ ├── forkify-architecture-recipe-loading.png │ ├── forkify-flowchart-part-1.png │ ├── forkify-flowchart-part-2.png │ ├── forkify-flowchart-part-3.png │ ├── index.html │ └── src │ ├── img │ ├── favicon.png │ ├── icons.svg │ └── logo.png │ ├── js │ └── controller.js │ └── sass │ ├── _base.scss │ ├── _components.scss │ ├── _header.scss │ ├── _preview.scss │ ├── _recipe.scss │ ├── _searchResults.scss │ ├── _upload.scss │ └── main.scss └── README.md /01-Fundamentals-Part-1/final/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | JavaScript Fundamentals – Part 1 8 | 25 | 26 | 27 |

JavaScript Fundamentals – Part 1

28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /01-Fundamentals-Part-1/starter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | JavaScript Fundamentals – Part 1 8 | 25 | 26 | 27 |

JavaScript Fundamentals – Part 1

28 | 29 | 30 | -------------------------------------------------------------------------------- /02-Fundamentals-Part-2/final/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | JavaScript Fundamentals – Part 2 8 | 25 | 26 | 27 |

JavaScript Fundamentals – Part 2

28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /02-Fundamentals-Part-2/starter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | JavaScript Fundamentals – Part 2 8 | 25 | 26 | 27 |

JavaScript Fundamentals – Part 2

28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /02-Fundamentals-Part-2/starter/script.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/02-Fundamentals-Part-2/starter/script.js -------------------------------------------------------------------------------- /03-Developer-Skills/final/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /03-Developer-Skills/final/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Developer Skills & Editor Setup 8 | 25 | 26 | 27 |

Developer Skills & Editor Setup

28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /03-Developer-Skills/final/script.js: -------------------------------------------------------------------------------- 1 | // Remember, we're gonna use strict mode in all scripts now! 2 | 'use strict'; 3 | 4 | /* 5 | /////////////////////////////////////// 6 | // Using Google, StackOverflow and MDN 7 | 8 | // PROBLEM 1: 9 | // We work for a company building a smart home thermometer. Our most recent task is this: "Given an array of temperatures of one day, calculate the temperature amplitude. Keep in mind that sometimes there might be a sensor error." 10 | 11 | const temperatures = [3, -2, -6, -1, 'error', 9, 13, 17, 15, 14, 9, 5]; 12 | 13 | // 1) Understanding the problem 14 | // - What is temp amplitude? Answer: difference between highest and lowest temp 15 | // - How to compute max and min temperatures? 16 | // - What's a sensor error? And what do do? 17 | 18 | // 2) Breaking up into sub-problems 19 | // - How to ignore errors? 20 | // - Find max value in temp array 21 | // - Find min value in temp array 22 | // - Subtract min from max (amplitude) and return it 23 | 24 | const calcTempAmplitude = function (temps) { 25 | let max = temps[0]; 26 | let min = temps[0]; 27 | 28 | for (let i = 0; i < temps.length; i++) { 29 | const curTemp = temps[i]; 30 | if (typeof curTemp !== 'number') continue; 31 | 32 | if (curTemp > max) max = curTemp; 33 | if (curTemp < min) min = curTemp; 34 | } 35 | console.log(max, min); 36 | return max - min; 37 | }; 38 | const amplitude = calcTempAmplitude(temperatures); 39 | console.log(amplitude); 40 | 41 | // PROBLEM 2: 42 | // Function should now receive 2 arrays of temps 43 | 44 | // 1) Understanding the problem 45 | // - With 2 arrays, should we implement functionality twice? NO! Just merge two arrays 46 | 47 | // 2) Breaking up into sub-problems 48 | // - Merge 2 arrays 49 | 50 | const calcTempAmplitudeNew = function (t1, t2) { 51 | const temps = t1.concat(t2); 52 | console.log(temps); 53 | 54 | let max = temps[0]; 55 | let min = temps[0]; 56 | 57 | for (let i = 0; i < temps.length; i++) { 58 | const curTemp = temps[i]; 59 | if (typeof curTemp !== 'number') continue; 60 | 61 | if (curTemp > max) max = curTemp; 62 | if (curTemp < min) min = curTemp; 63 | } 64 | console.log(max, min); 65 | return max - min; 66 | }; 67 | const amplitudeNew = calcTempAmplitudeNew([3, 5, 1], [9, 0, 5]); 68 | console.log(amplitudeNew); 69 | 70 | 71 | /////////////////////////////////////// 72 | // Debugging with the Console and Breakpoints 73 | const measureKelvin = function () { 74 | const measurement = { 75 | type: 'temp', 76 | unit: 'celsius', 77 | 78 | // C) FIX 79 | // value: Number(prompt('Degrees celsius:')), 80 | value: 10, 81 | }; 82 | 83 | // B) FIND 84 | console.table(measurement); 85 | 86 | // console.log(measurement.value); 87 | // console.warn(measurement.value); 88 | // console.error(measurement.value); 89 | 90 | const kelvin = measurement.value + 273; 91 | return kelvin; 92 | }; 93 | // A) IDENTIFY 94 | console.log(measureKelvin()); 95 | 96 | // Using a debugger 97 | const calcTempAmplitudeBug = function (t1, t2) { 98 | const temps = t1.concat(t2); 99 | console.log(temps); 100 | 101 | let max = 0; 102 | let min = 0; 103 | 104 | for (let i = 0; i < temps.length; i++) { 105 | const curTemp = temps[i]; 106 | if (typeof curTemp !== 'number') continue; 107 | 108 | if (curTemp > max) max = curTemp; 109 | if (curTemp < min) min = curTemp; 110 | } 111 | console.log(max, min); 112 | return max - min; 113 | }; 114 | const amplitudeBug = calcTempAmplitudeBug([3, 5, 1], [9, 4, 5]); 115 | // A) IDENTIFY 116 | console.log(amplitudeBug); 117 | */ 118 | 119 | /////////////////////////////////////// 120 | // Coding Challenge #1 121 | 122 | /* 123 | Given an array of forecasted maximum temperatures, the thermometer displays a string with these temperatures. 124 | 125 | Example: [17, 21, 23] will print "... 17ºC in 1 days ... 21ºC in 2 days ... 23ºC in 3 days ..." 126 | 127 | Create a function 'printForecast' which takes in an array 'arr' and logs a string like the above to the console. 128 | 129 | Use the problem-solving framework: Understand the problem and break it up into sub-problems! 130 | 131 | TEST DATA 1: [17, 21, 23] 132 | TEST DATA 2: [12, 5, -5, 0, 4] 133 | */ 134 | 135 | /* 136 | // 1) Understanding the problem 137 | // - Array transformed to string, separated by ... 138 | // - What is the X days? Answer: index + 1 139 | 140 | // 2) Breaking up into sub-problems 141 | // - Transform array into string 142 | // - Transform each element to string with ºC 143 | // - Strings needs to contain day (index + 1) 144 | // - Add ... between elements and start and end of string 145 | // - Log string to console 146 | 147 | const data1 = [17, 21, 23]; 148 | const data2 = [12, 5, -5, 0, 4]; 149 | 150 | console.log(`... ${data1[0]}ºC ... ${data1[1]}ºC ... ${data1[2]}ºC ...`); 151 | 152 | const printForecast = function (arr) { 153 | let str = ''; 154 | for (let i = 0; i < arr.length; i++) { 155 | str += `${arr[i]}ºC in ${i + 1} days ... `; 156 | } 157 | console.log('...' + str); 158 | }; 159 | printForecast(data1); 160 | */ 161 | 162 | -------------------------------------------------------------------------------- /03-Developer-Skills/starter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Developer Skills & Editor Setup 8 | 25 | 26 | 27 |

Developer Skills & Editor Setup

28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /03-Developer-Skills/starter/script.js: -------------------------------------------------------------------------------- 1 | // Remember, we're gonna use strict mode in all scripts now! 2 | 'use strict'; 3 | 4 | -------------------------------------------------------------------------------- /04-HTML-CSS/final/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Learning HTML & CSS 10 | 11 | 12 |

JavaScript is fun, but so is HTML & CSS!

13 |

14 | You can learn JavaScript without HTML and CSS, but for DOM manipulation 15 | it's useful to have some basic ideas of HTML & CSS. You can learn more 16 | about it 17 | on Udemy. 18 |

19 | 20 |

Another heading

21 |

22 | Just another paragraph 23 |

24 | 25 | 29 | 30 |
31 |

Your name here

32 |

Please fill in this form :)

33 | 34 | 35 | 36 |
37 | 38 | 39 | -------------------------------------------------------------------------------- /04-HTML-CSS/final/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | background-color: rgb(255, 247, 201); 9 | font-family: Arial; 10 | font-size: 20px; 11 | padding: 50px; 12 | } 13 | 14 | h1 { 15 | font-size: 35px; 16 | margin-bottom: 25px; 17 | } 18 | 19 | h2 { 20 | margin-bottom: 20px; 21 | text-align: center; 22 | } 23 | 24 | p { 25 | margin-bottom: 20px; 26 | } 27 | 28 | .first { 29 | color: red; 30 | } 31 | 32 | #your-name { 33 | background-color: rgb(255, 220, 105); 34 | border: 5px solid #444; 35 | width: 400px; 36 | padding: 25px; 37 | margin-top: 30px; 38 | } 39 | 40 | input, 41 | button { 42 | padding: 10px; 43 | font-size: 16px; 44 | } 45 | 46 | a { 47 | background-color: yellowgreen; 48 | } 49 | 50 | #course-image { 51 | width: 300px; 52 | } 53 | 54 | #your-name h2 { 55 | color: olivedrab; 56 | } 57 | -------------------------------------------------------------------------------- /05-Guess-My-Number/final/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /05-Guess-My-Number/final/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Guess My Number! 9 | 10 | 11 |
12 |

Guess My Number!

13 |

(Between 1 and 20)

14 | 15 |
?
16 |
17 |
18 |
19 | 20 | 21 |
22 |
23 |

Start guessing...

24 |

💯 Score: 20

25 |

26 | 🥇 Highscore: 0 27 |

28 |
29 |
30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /05-Guess-My-Number/final/script.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* 4 | console.log(document.querySelector('.message').textContent); 5 | document.querySelector('.message').textContent = '🎉 Correct Number!'; 6 | 7 | document.querySelector('.number').textContent = 13; 8 | document.querySelector('.score').textContent = 10; 9 | 10 | document.querySelector('.guess').value = 23; 11 | console.log(document.querySelector('.guess').value); 12 | */ 13 | 14 | let secretNumber = Math.trunc(Math.random() * 20) + 1; 15 | let score = 20; 16 | let highscore = 0; 17 | 18 | const displayMessage = function (message) { 19 | document.querySelector('.message').textContent = message; 20 | }; 21 | 22 | document.querySelector('.check').addEventListener('click', function () { 23 | const guess = Number(document.querySelector('.guess').value); 24 | console.log(guess, typeof guess); 25 | 26 | // When there is no input 27 | if (!guess) { 28 | // document.querySelector('.message').textContent = '⛔️ No number!'; 29 | displayMessage('⛔️ No number!'); 30 | 31 | // When player wins 32 | } else if (guess === secretNumber) { 33 | // document.querySelector('.message').textContent = '🎉 Correct Number!'; 34 | displayMessage('🎉 Correct Number!'); 35 | document.querySelector('.number').textContent = secretNumber; 36 | 37 | document.querySelector('body').style.backgroundColor = '#60b347'; 38 | document.querySelector('.number').style.width = '30rem'; 39 | 40 | if (score > highscore) { 41 | highscore = score; 42 | document.querySelector('.highscore').textContent = highscore; 43 | } 44 | 45 | // When guess is wrong 46 | } else if (guess !== secretNumber) { 47 | if (score > 1) { 48 | // document.querySelector('.message').textContent = 49 | // guess > secretNumber ? '📈 Too high!' : '📉 Too low!'; 50 | displayMessage(guess > secretNumber ? '📈 Too high!' : '📉 Too low!'); 51 | score--; 52 | document.querySelector('.score').textContent = score; 53 | } else { 54 | // document.querySelector('.message').textContent = '💥 You lost the game!'; 55 | displayMessage('💥 You lost the game!'); 56 | document.querySelector('.score').textContent = 0; 57 | } 58 | } 59 | 60 | // // When guess is too high 61 | // } else if (guess > secretNumber) { 62 | // if (score > 1) { 63 | // document.querySelector('.message').textContent = '📈 Too high!'; 64 | // score--; 65 | // document.querySelector('.score').textContent = score; 66 | // } else { 67 | // document.querySelector('.message').textContent = '💥 You lost the game!'; 68 | // document.querySelector('.score').textContent = 0; 69 | // } 70 | 71 | // // When guess is too low 72 | // } else if (guess < secretNumber) { 73 | // if (score > 1) { 74 | // document.querySelector('.message').textContent = '📉 Too low!'; 75 | // score--; 76 | // document.querySelector('.score').textContent = score; 77 | // } else { 78 | // document.querySelector('.message').textContent = '💥 You lost the game!'; 79 | // document.querySelector('.score').textContent = 0; 80 | // } 81 | // } 82 | }); 83 | 84 | document.querySelector('.again').addEventListener('click', function () { 85 | score = 20; 86 | secretNumber = Math.trunc(Math.random() * 20) + 1; 87 | 88 | // document.querySelector('.message').textContent = 'Start guessing...'; 89 | displayMessage('Start guessing...'); 90 | document.querySelector('.score').textContent = score; 91 | document.querySelector('.number').textContent = '?'; 92 | document.querySelector('.guess').value = ''; 93 | 94 | document.querySelector('body').style.backgroundColor = '#222'; 95 | document.querySelector('.number').style.width = '15rem'; 96 | }); 97 | 98 | /////////////////////////////////////// 99 | // Coding Challenge #1 100 | 101 | /* 102 | Implement a game rest functionality, so that the player can make a new guess! Here is how: 103 | 104 | 1. Select the element with the 'again' class and attach a click event handler 105 | 2. In the handler function, restore initial values of the score and secretNumber variables 106 | 3. Restore the initial conditions of the message, number, score and guess input field 107 | 4. Also restore the original background color (#222) and number width (15rem) 108 | 109 | GOOD LUCK 😀 110 | */ 111 | -------------------------------------------------------------------------------- /05-Guess-My-Number/final/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Press+Start+2P&display=swap'); 2 | 3 | * { 4 | margin: 0; 5 | padding: 0; 6 | box-sizing: inherit; 7 | } 8 | 9 | html { 10 | font-size: 62.5%; 11 | box-sizing: border-box; 12 | } 13 | 14 | body { 15 | font-family: 'Press Start 2P', sans-serif; 16 | color: #eee; 17 | background-color: #222; 18 | /* background-color: #60b347; */ 19 | } 20 | 21 | /* LAYOUT */ 22 | header { 23 | position: relative; 24 | height: 35vh; 25 | border-bottom: 7px solid #eee; 26 | } 27 | 28 | main { 29 | height: 65vh; 30 | color: #eee; 31 | display: flex; 32 | align-items: center; 33 | justify-content: space-around; 34 | } 35 | 36 | .left { 37 | width: 52rem; 38 | display: flex; 39 | flex-direction: column; 40 | align-items: center; 41 | } 42 | 43 | .right { 44 | width: 52rem; 45 | font-size: 2rem; 46 | } 47 | 48 | /* ELEMENTS STYLE */ 49 | h1 { 50 | font-size: 4rem; 51 | text-align: center; 52 | position: absolute; 53 | width: 100%; 54 | top: 52%; 55 | left: 50%; 56 | transform: translate(-50%, -50%); 57 | } 58 | 59 | .number { 60 | background: #eee; 61 | color: #333; 62 | font-size: 6rem; 63 | width: 15rem; 64 | padding: 3rem 0rem; 65 | text-align: center; 66 | position: absolute; 67 | bottom: 0; 68 | left: 50%; 69 | transform: translate(-50%, 50%); 70 | } 71 | 72 | .between { 73 | font-size: 1.4rem; 74 | position: absolute; 75 | top: 2rem; 76 | right: 2rem; 77 | } 78 | 79 | .again { 80 | position: absolute; 81 | top: 2rem; 82 | left: 2rem; 83 | } 84 | 85 | .guess { 86 | background: none; 87 | border: 4px solid #eee; 88 | font-family: inherit; 89 | color: inherit; 90 | font-size: 5rem; 91 | padding: 2.5rem; 92 | width: 25rem; 93 | text-align: center; 94 | display: block; 95 | margin-bottom: 3rem; 96 | } 97 | 98 | .btn { 99 | border: none; 100 | background-color: #eee; 101 | color: #222; 102 | font-size: 2rem; 103 | font-family: inherit; 104 | padding: 2rem 3rem; 105 | cursor: pointer; 106 | } 107 | 108 | .btn:hover { 109 | background-color: #ccc; 110 | } 111 | 112 | .message { 113 | margin-bottom: 8rem; 114 | height: 3rem; 115 | } 116 | 117 | .label-score { 118 | margin-bottom: 2rem; 119 | } 120 | -------------------------------------------------------------------------------- /05-Guess-My-Number/starter/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /05-Guess-My-Number/starter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Guess My Number! 9 | 10 | 11 |
12 |

Guess My Number!

13 |

(Between 1 and 20)

14 | 15 |
?
16 |
17 |
18 |
19 | 20 | 21 |
22 |
23 |

Start guessing...

24 |

💯 Score: 20

25 |

26 | 🥇 Highscore: 0 27 |

28 |
29 |
30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /05-Guess-My-Number/starter/script.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | -------------------------------------------------------------------------------- /05-Guess-My-Number/starter/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Press+Start+2P&display=swap'); 2 | 3 | * { 4 | margin: 0; 5 | padding: 0; 6 | box-sizing: inherit; 7 | } 8 | 9 | html { 10 | font-size: 62.5%; 11 | box-sizing: border-box; 12 | } 13 | 14 | body { 15 | font-family: 'Press Start 2P', sans-serif; 16 | color: #eee; 17 | background-color: #222; 18 | /* background-color: #60b347; */ 19 | } 20 | 21 | /* LAYOUT */ 22 | header { 23 | position: relative; 24 | height: 35vh; 25 | border-bottom: 7px solid #eee; 26 | } 27 | 28 | main { 29 | height: 65vh; 30 | color: #eee; 31 | display: flex; 32 | align-items: center; 33 | justify-content: space-around; 34 | } 35 | 36 | .left { 37 | width: 52rem; 38 | display: flex; 39 | flex-direction: column; 40 | align-items: center; 41 | } 42 | 43 | .right { 44 | width: 52rem; 45 | font-size: 2rem; 46 | } 47 | 48 | /* ELEMENTS STYLE */ 49 | h1 { 50 | font-size: 4rem; 51 | text-align: center; 52 | position: absolute; 53 | width: 100%; 54 | top: 52%; 55 | left: 50%; 56 | transform: translate(-50%, -50%); 57 | } 58 | 59 | .number { 60 | background: #eee; 61 | color: #333; 62 | font-size: 6rem; 63 | width: 15rem; 64 | padding: 3rem 0rem; 65 | text-align: center; 66 | position: absolute; 67 | bottom: 0; 68 | left: 50%; 69 | transform: translate(-50%, 50%); 70 | } 71 | 72 | .between { 73 | font-size: 1.4rem; 74 | position: absolute; 75 | top: 2rem; 76 | right: 2rem; 77 | } 78 | 79 | .again { 80 | position: absolute; 81 | top: 2rem; 82 | left: 2rem; 83 | } 84 | 85 | .guess { 86 | background: none; 87 | border: 4px solid #eee; 88 | font-family: inherit; 89 | color: inherit; 90 | font-size: 5rem; 91 | padding: 2.5rem; 92 | width: 25rem; 93 | text-align: center; 94 | display: block; 95 | margin-bottom: 3rem; 96 | } 97 | 98 | .btn { 99 | border: none; 100 | background-color: #eee; 101 | color: #222; 102 | font-size: 2rem; 103 | font-family: inherit; 104 | padding: 2rem 3rem; 105 | cursor: pointer; 106 | } 107 | 108 | .btn:hover { 109 | background-color: #ccc; 110 | } 111 | 112 | .message { 113 | margin-bottom: 8rem; 114 | height: 3rem; 115 | } 116 | 117 | .label-score { 118 | margin-bottom: 2rem; 119 | } 120 | -------------------------------------------------------------------------------- /06-Modal/final/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /06-Modal/final/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Modal window 9 | 10 | 11 | 12 | 13 | 14 | 15 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /06-Modal/final/script.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const modal = document.querySelector('.modal'); 4 | const overlay = document.querySelector('.overlay'); 5 | const btnCloseModal = document.querySelector('.close-modal'); 6 | const btnsOpenModal = document.querySelectorAll('.show-modal'); 7 | 8 | const openModal = function () { 9 | modal.classList.remove('hidden'); 10 | overlay.classList.remove('hidden'); 11 | }; 12 | 13 | const closeModal = function () { 14 | modal.classList.add('hidden'); 15 | overlay.classList.add('hidden'); 16 | }; 17 | 18 | for (let i = 0; i < btnsOpenModal.length; i++) 19 | btnsOpenModal[i].addEventListener('click', openModal); 20 | 21 | btnCloseModal.addEventListener('click', closeModal); 22 | overlay.addEventListener('click', closeModal); 23 | 24 | document.addEventListener('keydown', function (e) { 25 | // console.log(e.key); 26 | 27 | if (e.key === 'Escape' && !modal.classList.contains('hidden')) { 28 | closeModal(); 29 | } 30 | }); 31 | -------------------------------------------------------------------------------- /06-Modal/final/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: inherit; 5 | } 6 | 7 | html { 8 | font-size: 62.5%; 9 | box-sizing: border-box; 10 | } 11 | 12 | body { 13 | font-family: sans-serif; 14 | color: #333; 15 | line-height: 1.5; 16 | height: 100vh; 17 | position: relative; 18 | display: flex; 19 | align-items: flex-start; 20 | justify-content: center; 21 | background: linear-gradient(to top left, #28b487, #7dd56f); 22 | } 23 | 24 | .show-modal { 25 | font-size: 2rem; 26 | font-weight: 600; 27 | padding: 1.75rem 3.5rem; 28 | margin: 5rem 2rem; 29 | border: none; 30 | background-color: #fff; 31 | color: #444; 32 | border-radius: 10rem; 33 | cursor: pointer; 34 | } 35 | 36 | .close-modal { 37 | position: absolute; 38 | top: 1.2rem; 39 | right: 2rem; 40 | font-size: 5rem; 41 | color: #333; 42 | cursor: pointer; 43 | border: none; 44 | background: none; 45 | } 46 | 47 | h1 { 48 | font-size: 2.5rem; 49 | margin-bottom: 2rem; 50 | } 51 | 52 | p { 53 | font-size: 1.8rem; 54 | } 55 | 56 | /* -------------------------- */ 57 | /* CLASSES TO MAKE MODAL WORK */ 58 | .hidden { 59 | display: none; 60 | } 61 | 62 | .modal { 63 | position: absolute; 64 | top: 50%; 65 | left: 50%; 66 | transform: translate(-50%, -50%); 67 | width: 70%; 68 | 69 | background-color: white; 70 | padding: 6rem; 71 | border-radius: 5px; 72 | box-shadow: 0 3rem 5rem rgba(0, 0, 0, 0.3); 73 | z-index: 10; 74 | } 75 | 76 | .overlay { 77 | position: absolute; 78 | top: 0; 79 | left: 0; 80 | width: 100%; 81 | height: 100%; 82 | background-color: rgba(0, 0, 0, 0.6); 83 | backdrop-filter: blur(3px); 84 | z-index: 5; 85 | } 86 | -------------------------------------------------------------------------------- /06-Modal/starter/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /06-Modal/starter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Modal window 9 | 10 | 11 | 12 | 13 | 14 | 15 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /06-Modal/starter/script.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | -------------------------------------------------------------------------------- /06-Modal/starter/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: inherit; 5 | } 6 | 7 | html { 8 | font-size: 62.5%; 9 | box-sizing: border-box; 10 | } 11 | 12 | body { 13 | font-family: sans-serif; 14 | color: #333; 15 | line-height: 1.5; 16 | height: 100vh; 17 | position: relative; 18 | display: flex; 19 | align-items: flex-start; 20 | justify-content: center; 21 | background: linear-gradient(to top left, #28b487, #7dd56f); 22 | } 23 | 24 | .show-modal { 25 | font-size: 2rem; 26 | font-weight: 600; 27 | padding: 1.75rem 3.5rem; 28 | margin: 5rem 2rem; 29 | border: none; 30 | background-color: #fff; 31 | color: #444; 32 | border-radius: 10rem; 33 | cursor: pointer; 34 | } 35 | 36 | .close-modal { 37 | position: absolute; 38 | top: 1.2rem; 39 | right: 2rem; 40 | font-size: 5rem; 41 | color: #333; 42 | cursor: pointer; 43 | border: none; 44 | background: none; 45 | } 46 | 47 | h1 { 48 | font-size: 2.5rem; 49 | margin-bottom: 2rem; 50 | } 51 | 52 | p { 53 | font-size: 1.8rem; 54 | } 55 | 56 | /* -------------------------- */ 57 | /* CLASSES TO MAKE MODAL WORK */ 58 | .hidden { 59 | display: none; 60 | } 61 | 62 | .modal { 63 | position: absolute; 64 | top: 50%; 65 | left: 50%; 66 | transform: translate(-50%, -50%); 67 | width: 70%; 68 | 69 | background-color: white; 70 | padding: 6rem; 71 | border-radius: 5px; 72 | box-shadow: 0 3rem 5rem rgba(0, 0, 0, 0.3); 73 | z-index: 10; 74 | } 75 | 76 | .overlay { 77 | position: absolute; 78 | top: 0; 79 | left: 0; 80 | width: 100%; 81 | height: 100%; 82 | background-color: rgba(0, 0, 0, 0.6); 83 | backdrop-filter: blur(3px); 84 | z-index: 5; 85 | } 86 | -------------------------------------------------------------------------------- /07-Pig-Game/final/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /07-Pig-Game/final/dice-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/final/dice-1.png -------------------------------------------------------------------------------- /07-Pig-Game/final/dice-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/final/dice-2.png -------------------------------------------------------------------------------- /07-Pig-Game/final/dice-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/final/dice-3.png -------------------------------------------------------------------------------- /07-Pig-Game/final/dice-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/final/dice-4.png -------------------------------------------------------------------------------- /07-Pig-Game/final/dice-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/final/dice-5.png -------------------------------------------------------------------------------- /07-Pig-Game/final/dice-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/final/dice-6.png -------------------------------------------------------------------------------- /07-Pig-Game/final/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Pig Game 9 | 10 | 11 |
12 |
13 |

Player 1

14 |

43

15 |
16 |

Current

17 |

0

18 |
19 |
20 |
21 |

Player 2

22 |

24

23 |
24 |

Current

25 |

0

26 |
27 |
28 | 29 | Playing dice 30 | 31 | 32 | 33 |
34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /07-Pig-Game/final/pig-game-flowchart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/final/pig-game-flowchart.png -------------------------------------------------------------------------------- /07-Pig-Game/final/script.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Selecting elements 4 | const player0El = document.querySelector('.player--0'); 5 | const player1El = document.querySelector('.player--1'); 6 | const score0El = document.querySelector('#score--0'); 7 | const score1El = document.getElementById('score--1'); 8 | const current0El = document.getElementById('current--0'); 9 | const current1El = document.getElementById('current--1'); 10 | 11 | const diceEl = document.querySelector('.dice'); 12 | const btnNew = document.querySelector('.btn--new'); 13 | const btnRoll = document.querySelector('.btn--roll'); 14 | const btnHold = document.querySelector('.btn--hold'); 15 | 16 | let scores, currentScore, activePlayer, playing; 17 | 18 | // Starting conditions 19 | const init = function () { 20 | scores = [0, 0]; 21 | currentScore = 0; 22 | activePlayer = 0; 23 | playing = true; 24 | 25 | score0El.textContent = 0; 26 | score1El.textContent = 0; 27 | current0El.textContent = 0; 28 | current1El.textContent = 0; 29 | 30 | diceEl.classList.add('hidden'); 31 | player0El.classList.remove('player--winner'); 32 | player1El.classList.remove('player--winner'); 33 | player0El.classList.add('player--active'); 34 | player1El.classList.remove('player--active'); 35 | }; 36 | init(); 37 | 38 | const switchPlayer = function () { 39 | document.getElementById(`current--${activePlayer}`).textContent = 0; 40 | currentScore = 0; 41 | activePlayer = activePlayer === 0 ? 1 : 0; 42 | player0El.classList.toggle('player--active'); 43 | player1El.classList.toggle('player--active'); 44 | }; 45 | 46 | // Rolling dice functionality 47 | btnRoll.addEventListener('click', function () { 48 | if (playing) { 49 | // 1. Generating a random dice roll 50 | const dice = Math.trunc(Math.random() * 6) + 1; 51 | 52 | // 2. Display dice 53 | diceEl.classList.remove('hidden'); 54 | diceEl.src = `dice-${dice}.png`; 55 | 56 | // 3. Check for rolled 1 57 | if (dice !== 1) { 58 | // Add dice to current score 59 | currentScore += dice; 60 | document.getElementById( 61 | `current--${activePlayer}` 62 | ).textContent = currentScore; 63 | } else { 64 | // Switch to next player 65 | switchPlayer(); 66 | } 67 | } 68 | }); 69 | 70 | btnHold.addEventListener('click', function () { 71 | if (playing) { 72 | // 1. Add current score to active player's score 73 | scores[activePlayer] += currentScore; 74 | // scores[1] = scores[1] + currentScore 75 | 76 | document.getElementById(`score--${activePlayer}`).textContent = 77 | scores[activePlayer]; 78 | 79 | // 2. Check if player's score is >= 100 80 | if (scores[activePlayer] >= 100) { 81 | // Finish the game 82 | playing = false; 83 | diceEl.classList.add('hidden'); 84 | 85 | document 86 | .querySelector(`.player--${activePlayer}`) 87 | .classList.add('player--winner'); 88 | document 89 | .querySelector(`.player--${activePlayer}`) 90 | .classList.remove('player--active'); 91 | } else { 92 | // Switch to the next player 93 | switchPlayer(); 94 | } 95 | } 96 | }); 97 | 98 | btnNew.addEventListener('click', init); 99 | -------------------------------------------------------------------------------- /07-Pig-Game/final/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Nunito&display=swap'); 2 | 3 | * { 4 | margin: 0; 5 | padding: 0; 6 | box-sizing: inherit; 7 | } 8 | 9 | html { 10 | font-size: 62.5%; 11 | box-sizing: border-box; 12 | } 13 | 14 | body { 15 | font-family: 'Nunito', sans-serif; 16 | font-weight: 400; 17 | height: 100vh; 18 | color: #333; 19 | background-image: linear-gradient(to top left, #753682 0%, #bf2e34 100%); 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | } 24 | 25 | /* LAYOUT */ 26 | main { 27 | position: relative; 28 | width: 100rem; 29 | height: 60rem; 30 | background-color: rgba(255, 255, 255, 0.35); 31 | backdrop-filter: blur(200px); 32 | filter: blur(); 33 | box-shadow: 0 3rem 5rem rgba(0, 0, 0, 0.25); 34 | border-radius: 9px; 35 | overflow: hidden; 36 | display: flex; 37 | } 38 | 39 | .player { 40 | flex: 50%; 41 | padding: 9rem; 42 | display: flex; 43 | flex-direction: column; 44 | align-items: center; 45 | transition: all 0.75s; 46 | } 47 | 48 | /* ELEMENTS */ 49 | .name { 50 | position: relative; 51 | font-size: 4rem; 52 | text-transform: uppercase; 53 | letter-spacing: 1px; 54 | word-spacing: 2px; 55 | font-weight: 300; 56 | margin-bottom: 1rem; 57 | } 58 | 59 | .score { 60 | font-size: 8rem; 61 | font-weight: 300; 62 | color: #c7365f; 63 | margin-bottom: auto; 64 | } 65 | 66 | .player--active { 67 | background-color: rgba(255, 255, 255, 0.4); 68 | } 69 | .player--active .name { 70 | font-weight: 700; 71 | } 72 | .player--active .score { 73 | font-weight: 400; 74 | } 75 | 76 | .player--active .current { 77 | opacity: 1; 78 | } 79 | 80 | .current { 81 | background-color: #c7365f; 82 | opacity: 0.8; 83 | border-radius: 9px; 84 | color: #fff; 85 | width: 65%; 86 | padding: 2rem; 87 | text-align: center; 88 | transition: all 0.75s; 89 | } 90 | 91 | .current-label { 92 | text-transform: uppercase; 93 | margin-bottom: 1rem; 94 | font-size: 1.7rem; 95 | color: #ddd; 96 | } 97 | 98 | .current-score { 99 | font-size: 3.5rem; 100 | } 101 | 102 | /* ABSOLUTE POSITIONED ELEMENTS */ 103 | .btn { 104 | position: absolute; 105 | left: 50%; 106 | transform: translateX(-50%); 107 | color: #444; 108 | background: none; 109 | border: none; 110 | font-family: inherit; 111 | font-size: 1.8rem; 112 | text-transform: uppercase; 113 | cursor: pointer; 114 | font-weight: 400; 115 | transition: all 0.2s; 116 | 117 | background-color: white; 118 | background-color: rgba(255, 255, 255, 0.6); 119 | backdrop-filter: blur(10px); 120 | 121 | padding: 0.7rem 2.5rem; 122 | border-radius: 50rem; 123 | box-shadow: 0 1.75rem 3.5rem rgba(0, 0, 0, 0.1); 124 | } 125 | 126 | .btn::first-letter { 127 | font-size: 2.4rem; 128 | display: inline-block; 129 | margin-right: 0.7rem; 130 | } 131 | 132 | .btn--new { 133 | top: 4rem; 134 | } 135 | .btn--roll { 136 | top: 39.3rem; 137 | } 138 | .btn--hold { 139 | top: 46.1rem; 140 | } 141 | 142 | .btn:active { 143 | transform: translate(-50%, 3px); 144 | box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.15); 145 | } 146 | 147 | .btn:focus { 148 | outline: none; 149 | } 150 | 151 | .dice { 152 | position: absolute; 153 | left: 50%; 154 | top: 16.5rem; 155 | transform: translateX(-50%); 156 | height: 10rem; 157 | box-shadow: 0 2rem 5rem rgba(0, 0, 0, 0.2); 158 | } 159 | 160 | .player--winner { 161 | background-color: #2f2f2f; 162 | } 163 | 164 | .player--winner .name { 165 | font-weight: 700; 166 | color: #c7365f; 167 | } 168 | 169 | .hidden { 170 | display: none; 171 | } 172 | -------------------------------------------------------------------------------- /07-Pig-Game/starter/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /07-Pig-Game/starter/dice-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/starter/dice-1.png -------------------------------------------------------------------------------- /07-Pig-Game/starter/dice-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/starter/dice-2.png -------------------------------------------------------------------------------- /07-Pig-Game/starter/dice-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/starter/dice-3.png -------------------------------------------------------------------------------- /07-Pig-Game/starter/dice-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/starter/dice-4.png -------------------------------------------------------------------------------- /07-Pig-Game/starter/dice-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/starter/dice-5.png -------------------------------------------------------------------------------- /07-Pig-Game/starter/dice-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/starter/dice-6.png -------------------------------------------------------------------------------- /07-Pig-Game/starter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Pig Game 9 | 10 | 11 |
12 |
13 |

Player 1

14 |

43

15 |
16 |

Current

17 |

0

18 |
19 |
20 |
21 |

Player 2

22 |

24

23 |
24 |

Current

25 |

0

26 |
27 |
28 | 29 | Playing dice 30 | 31 | 32 | 33 |
34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /07-Pig-Game/starter/pig-game-flowchart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/starter/pig-game-flowchart.png -------------------------------------------------------------------------------- /07-Pig-Game/starter/script.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | -------------------------------------------------------------------------------- /07-Pig-Game/starter/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Nunito&display=swap'); 2 | 3 | * { 4 | margin: 0; 5 | padding: 0; 6 | box-sizing: inherit; 7 | } 8 | 9 | html { 10 | font-size: 62.5%; 11 | box-sizing: border-box; 12 | } 13 | 14 | body { 15 | font-family: 'Nunito', sans-serif; 16 | font-weight: 400; 17 | height: 100vh; 18 | color: #333; 19 | background-image: linear-gradient(to top left, #753682 0%, #bf2e34 100%); 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | } 24 | 25 | /* LAYOUT */ 26 | main { 27 | position: relative; 28 | width: 100rem; 29 | height: 60rem; 30 | background-color: rgba(255, 255, 255, 0.35); 31 | backdrop-filter: blur(200px); 32 | filter: blur(); 33 | box-shadow: 0 3rem 5rem rgba(0, 0, 0, 0.25); 34 | border-radius: 9px; 35 | overflow: hidden; 36 | display: flex; 37 | } 38 | 39 | .player { 40 | flex: 50%; 41 | padding: 9rem; 42 | display: flex; 43 | flex-direction: column; 44 | align-items: center; 45 | transition: all 0.75s; 46 | } 47 | 48 | /* ELEMENTS */ 49 | .name { 50 | position: relative; 51 | font-size: 4rem; 52 | text-transform: uppercase; 53 | letter-spacing: 1px; 54 | word-spacing: 2px; 55 | font-weight: 300; 56 | margin-bottom: 1rem; 57 | } 58 | 59 | .score { 60 | font-size: 8rem; 61 | font-weight: 300; 62 | color: #c7365f; 63 | margin-bottom: auto; 64 | } 65 | 66 | .player--active { 67 | background-color: rgba(255, 255, 255, 0.4); 68 | } 69 | .player--active .name { 70 | font-weight: 700; 71 | } 72 | .player--active .score { 73 | font-weight: 400; 74 | } 75 | 76 | .player--active .current { 77 | opacity: 1; 78 | } 79 | 80 | .current { 81 | background-color: #c7365f; 82 | opacity: 0.8; 83 | border-radius: 9px; 84 | color: #fff; 85 | width: 65%; 86 | padding: 2rem; 87 | text-align: center; 88 | transition: all 0.75s; 89 | } 90 | 91 | .current-label { 92 | text-transform: uppercase; 93 | margin-bottom: 1rem; 94 | font-size: 1.7rem; 95 | color: #ddd; 96 | } 97 | 98 | .current-score { 99 | font-size: 3.5rem; 100 | } 101 | 102 | /* ABSOLUTE POSITIONED ELEMENTS */ 103 | .btn { 104 | position: absolute; 105 | left: 50%; 106 | transform: translateX(-50%); 107 | color: #444; 108 | background: none; 109 | border: none; 110 | font-family: inherit; 111 | font-size: 1.8rem; 112 | text-transform: uppercase; 113 | cursor: pointer; 114 | font-weight: 400; 115 | transition: all 0.2s; 116 | 117 | background-color: white; 118 | background-color: rgba(255, 255, 255, 0.6); 119 | backdrop-filter: blur(10px); 120 | 121 | padding: 0.7rem 2.5rem; 122 | border-radius: 50rem; 123 | box-shadow: 0 1.75rem 3.5rem rgba(0, 0, 0, 0.1); 124 | } 125 | 126 | .btn::first-letter { 127 | font-size: 2.4rem; 128 | display: inline-block; 129 | margin-right: 0.7rem; 130 | } 131 | 132 | .btn--new { 133 | top: 4rem; 134 | } 135 | .btn--roll { 136 | top: 39.3rem; 137 | } 138 | .btn--hold { 139 | top: 46.1rem; 140 | } 141 | 142 | .btn:active { 143 | transform: translate(-50%, 3px); 144 | box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.15); 145 | } 146 | 147 | .btn:focus { 148 | outline: none; 149 | } 150 | 151 | .dice { 152 | position: absolute; 153 | left: 50%; 154 | top: 16.5rem; 155 | transform: translateX(-50%); 156 | height: 10rem; 157 | box-shadow: 0 2rem 5rem rgba(0, 0, 0, 0.2); 158 | } 159 | 160 | .player--winner { 161 | background-color: #2f2f2f; 162 | } 163 | 164 | .player--winner .name { 165 | font-weight: 700; 166 | color: #c7365f; 167 | } 168 | -------------------------------------------------------------------------------- /08-Behind-the-Scenes/final/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /08-Behind-the-Scenes/final/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | How JavaScript Works Behind the Scenes 8 | 25 | 26 | 27 |

How JavaScript Works Behind the Scenes

28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /08-Behind-the-Scenes/starter/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /08-Behind-the-Scenes/starter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | How JavaScript Works Behind the Scenes 8 | 25 | 26 | 27 |

How JavaScript Works Behind the Scenes

28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /08-Behind-the-Scenes/starter/script.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | -------------------------------------------------------------------------------- /09-Data-Structures-Operators/final/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /09-Data-Structures-Operators/final/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Data Structures and Modern Operators 8 | 34 | 35 | 36 |

Data Structures and Modern Operators

37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /09-Data-Structures-Operators/starter/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /09-Data-Structures-Operators/starter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Data Structures and Modern Operators 8 | 34 | 35 | 36 |

Data Structures and Modern Operators

37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /09-Data-Structures-Operators/starter/script.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Data needed for a later exercise 4 | const flights = 5 | '_Delayed_Departure;fao93766109;txl2133758440;11:25+_Arrival;bru0943384722;fao93766109;11:45+_Delayed_Arrival;hel7439299980;fao93766109;12:05+_Departure;fao93766109;lis2323639855;12:30'; 6 | 7 | // Data needed for first part of the section 8 | const restaurant = { 9 | name: 'Classico Italiano', 10 | location: 'Via Angelo Tavanti 23, Firenze, Italy', 11 | categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'], 12 | starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'], 13 | mainMenu: ['Pizza', 'Pasta', 'Risotto'], 14 | 15 | openingHours: { 16 | thu: { 17 | open: 12, 18 | close: 22, 19 | }, 20 | fri: { 21 | open: 11, 22 | close: 23, 23 | }, 24 | sat: { 25 | open: 0, // Open 24 hours 26 | close: 24, 27 | }, 28 | }, 29 | }; 30 | -------------------------------------------------------------------------------- /10-Functions/final/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /10-Functions/final/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | A Closer Look at Functions 8 | 38 | 39 | 40 |

A Closer Look at Functions

41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /10-Functions/starter/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /10-Functions/starter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | A Closer Look at Functions 8 | 38 | 39 | 40 |

A Closer Look at Functions

41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /10-Functions/starter/script.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | -------------------------------------------------------------------------------- /11-Arrays-Bankist/final/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /11-Arrays-Bankist/final/Bankist-flowchart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/11-Arrays-Bankist/final/Bankist-flowchart.png -------------------------------------------------------------------------------- /11-Arrays-Bankist/final/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/11-Arrays-Bankist/final/icon.png -------------------------------------------------------------------------------- /11-Arrays-Bankist/final/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 15 | Bankist 16 | 17 | 18 | 19 | 38 | 39 |
40 | 41 |
42 |
43 |

Current balance

44 |

45 | As of 05/03/2037 46 |

47 |
48 |

0000€

49 |
50 | 51 | 52 |
53 |
54 |
2 deposit
55 |
3 days ago
56 |
4 000€
57 |
58 |
59 |
60 | 1 withdrawal 61 |
62 |
24/01/2037
63 |
-378€
64 |
65 |
66 | 67 | 68 |
69 |

In

70 |

0000€

71 |

Out

72 |

0000€

73 |

Interest

74 |

0000€

75 | 76 |
77 | 78 | 79 |
80 |

Transfer money

81 |
82 | 83 | 84 | 85 | 86 | 87 |
88 |
89 | 90 | 91 |
92 |

Request loan

93 |
94 | 95 | 96 | 97 |
98 |
99 | 100 | 101 |
102 |

Close account

103 |
104 | 105 | 110 | 111 | 112 | 113 |
114 |
115 | 116 | 117 |

118 | You will be logged out in 05:00 119 |

120 |
121 | 122 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /11-Arrays-Bankist/final/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/11-Arrays-Bankist/final/logo.png -------------------------------------------------------------------------------- /11-Arrays-Bankist/starter/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /11-Arrays-Bankist/starter/Bankist-flowchart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/11-Arrays-Bankist/starter/Bankist-flowchart.png -------------------------------------------------------------------------------- /11-Arrays-Bankist/starter/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/11-Arrays-Bankist/starter/icon.png -------------------------------------------------------------------------------- /11-Arrays-Bankist/starter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 15 | Bankist 16 | 17 | 18 | 19 | 38 | 39 |
40 | 41 |
42 |
43 |

Current balance

44 |

45 | As of 05/03/2037 46 |

47 |
48 |

0000€

49 |
50 | 51 | 52 |
53 |
54 |
2 deposit
55 |
3 days ago
56 |
4 000€
57 |
58 |
59 |
60 | 1 withdrawal 61 |
62 |
24/01/2037
63 |
-378€
64 |
65 |
66 | 67 | 68 |
69 |

In

70 |

0000€

71 |

Out

72 |

0000€

73 |

Interest

74 |

0000€

75 | 76 |
77 | 78 | 79 |
80 |

Transfer money

81 |
82 | 83 | 84 | 85 | 86 | 87 |
88 |
89 | 90 | 91 |
92 |

Request loan

93 |
94 | 95 | 96 | 97 |
98 |
99 | 100 | 101 |
102 |

Close account

103 |
104 | 105 | 110 | 111 | 112 | 113 |
114 |
115 | 116 | 117 |

118 | You will be logged out in 05:00 119 |

120 |
121 | 122 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /11-Arrays-Bankist/starter/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/11-Arrays-Bankist/starter/logo.png -------------------------------------------------------------------------------- /11-Arrays-Bankist/starter/script.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | ///////////////////////////////////////////////// 4 | ///////////////////////////////////////////////// 5 | // BANKIST APP 6 | 7 | // Data 8 | const account1 = { 9 | owner: 'Jonas Schmedtmann', 10 | movements: [200, 450, -400, 3000, -650, -130, 70, 1300], 11 | interestRate: 1.2, // % 12 | pin: 1111, 13 | }; 14 | 15 | const account2 = { 16 | owner: 'Jessica Davis', 17 | movements: [5000, 3400, -150, -790, -3210, -1000, 8500, -30], 18 | interestRate: 1.5, 19 | pin: 2222, 20 | }; 21 | 22 | const account3 = { 23 | owner: 'Steven Thomas Williams', 24 | movements: [200, -200, 340, -300, -20, 50, 400, -460], 25 | interestRate: 0.7, 26 | pin: 3333, 27 | }; 28 | 29 | const account4 = { 30 | owner: 'Sarah Smith', 31 | movements: [430, 1000, 700, 50, 90], 32 | interestRate: 1, 33 | pin: 4444, 34 | }; 35 | 36 | const accounts = [account1, account2, account3, account4]; 37 | 38 | // Elements 39 | const labelWelcome = document.querySelector('.welcome'); 40 | const labelDate = document.querySelector('.date'); 41 | const labelBalance = document.querySelector('.balance__value'); 42 | const labelSumIn = document.querySelector('.summary__value--in'); 43 | const labelSumOut = document.querySelector('.summary__value--out'); 44 | const labelSumInterest = document.querySelector('.summary__value--interest'); 45 | const labelTimer = document.querySelector('.timer'); 46 | 47 | const containerApp = document.querySelector('.app'); 48 | const containerMovements = document.querySelector('.movements'); 49 | 50 | const btnLogin = document.querySelector('.login__btn'); 51 | const btnTransfer = document.querySelector('.form__btn--transfer'); 52 | const btnLoan = document.querySelector('.form__btn--loan'); 53 | const btnClose = document.querySelector('.form__btn--close'); 54 | const btnSort = document.querySelector('.btn--sort'); 55 | 56 | const inputLoginUsername = document.querySelector('.login__input--user'); 57 | const inputLoginPin = document.querySelector('.login__input--pin'); 58 | const inputTransferTo = document.querySelector('.form__input--to'); 59 | const inputTransferAmount = document.querySelector('.form__input--amount'); 60 | const inputLoanAmount = document.querySelector('.form__input--loan-amount'); 61 | const inputCloseUsername = document.querySelector('.form__input--user'); 62 | const inputClosePin = document.querySelector('.form__input--pin'); 63 | 64 | ///////////////////////////////////////////////// 65 | ///////////////////////////////////////////////// 66 | // LECTURES 67 | 68 | const currencies = new Map([ 69 | ['USD', 'United States dollar'], 70 | ['EUR', 'Euro'], 71 | ['GBP', 'Pound sterling'], 72 | ]); 73 | 74 | const movements = [200, 450, -400, 3000, -650, -130, 70, 1300]; 75 | 76 | ///////////////////////////////////////////////// 77 | -------------------------------------------------------------------------------- /12-Numbers-Dates-Timers-Bankist/final/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /12-Numbers-Dates-Timers-Bankist/final/Bankist-flowchart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/12-Numbers-Dates-Timers-Bankist/final/Bankist-flowchart.png -------------------------------------------------------------------------------- /12-Numbers-Dates-Timers-Bankist/final/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/12-Numbers-Dates-Timers-Bankist/final/icon.png -------------------------------------------------------------------------------- /12-Numbers-Dates-Timers-Bankist/final/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 15 | Bankist 16 | 17 | 18 | 19 | 38 | 39 |
40 | 41 |
42 |
43 |

Current balance

44 |

45 | As of 05/03/2037 46 |

47 |
48 |

0000€

49 |
50 | 51 | 52 |
53 |
54 |
2 deposit
55 |
3 days ago
56 |
4 000€
57 |
58 |
59 |
60 | 1 withdrawal 61 |
62 |
24/01/2037
63 |
-378€
64 |
65 |
66 | 67 | 68 |
69 |

In

70 |

0000€

71 |

Out

72 |

0000€

73 |

Interest

74 |

0000€

75 | 76 |
77 | 78 | 79 |
80 |

Transfer money

81 |
82 | 83 | 84 | 85 | 86 | 87 |
88 |
89 | 90 | 91 |
92 |

Request loan

93 |
94 | 95 | 96 | 97 |
98 |
99 | 100 | 101 |
102 |

Close account

103 |
104 | 105 | 110 | 111 | 112 | 113 |
114 |
115 | 116 | 117 |

118 | You will be logged out in 05:00 119 |

120 |
121 | 122 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /12-Numbers-Dates-Timers-Bankist/final/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/12-Numbers-Dates-Timers-Bankist/final/logo.png -------------------------------------------------------------------------------- /12-Numbers-Dates-Timers-Bankist/starter/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /12-Numbers-Dates-Timers-Bankist/starter/Bankist-flowchart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/12-Numbers-Dates-Timers-Bankist/starter/Bankist-flowchart.png -------------------------------------------------------------------------------- /12-Numbers-Dates-Timers-Bankist/starter/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/12-Numbers-Dates-Timers-Bankist/starter/icon.png -------------------------------------------------------------------------------- /12-Numbers-Dates-Timers-Bankist/starter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 15 | Bankist 16 | 17 | 18 | 19 | 38 | 39 |
40 | 41 |
42 |
43 |

Current balance

44 |

45 | As of 05/03/2037 46 |

47 |
48 |

0000€

49 |
50 | 51 | 52 |
53 |
54 |
2 deposit
55 |
3 days ago
56 |
4 000€
57 |
58 |
59 |
60 | 1 withdrawal 61 |
62 |
24/01/2037
63 |
-378€
64 |
65 |
66 | 67 | 68 |
69 |

In

70 |

0000€

71 |

Out

72 |

0000€

73 |

Interest

74 |

0000€

75 | 76 |
77 | 78 | 79 |
80 |

Transfer money

81 |
82 | 83 | 84 | 85 | 86 | 87 |
88 |
89 | 90 | 91 |
92 |

Request loan

93 |
94 | 95 | 96 | 97 |
98 |
99 | 100 | 101 |
102 |

Close account

103 |
104 | 105 | 110 | 111 | 112 | 113 |
114 |
115 | 116 | 117 |

118 | You will be logged out in 05:00 119 |

120 |
121 | 122 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /12-Numbers-Dates-Timers-Bankist/starter/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/12-Numbers-Dates-Timers-Bankist/starter/logo.png -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/card-lazy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/card-lazy.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/card.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/card.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/digital-lazy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/digital-lazy.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/digital.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/digital.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/grow-lazy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/grow-lazy.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/grow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/grow.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/hero.png -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/icon.png -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/img-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/img-1.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/img-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/img-2.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/img-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/img-3.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/img-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/img-4.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/logo.png -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/user-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/user-1.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/user-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/user-2.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/user-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/user-3.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/card-lazy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/card-lazy.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/card.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/card.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/digital-lazy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/digital-lazy.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/digital.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/digital.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/grow-lazy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/grow-lazy.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/grow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/grow.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/hero.png -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/icon.png -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/img-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/img-1.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/img-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/img-2.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/img-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/img-3.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/img-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/img-4.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/logo.png -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/user-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/user-1.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/user-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/user-2.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/user-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/user-3.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/script.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /////////////////////////////////////// 4 | // Modal window 5 | 6 | const modal = document.querySelector('.modal'); 7 | const overlay = document.querySelector('.overlay'); 8 | const btnCloseModal = document.querySelector('.btn--close-modal'); 9 | const btnsOpenModal = document.querySelectorAll('.btn--show-modal'); 10 | 11 | const openModal = function () { 12 | modal.classList.remove('hidden'); 13 | overlay.classList.remove('hidden'); 14 | }; 15 | 16 | const closeModal = function () { 17 | modal.classList.add('hidden'); 18 | overlay.classList.add('hidden'); 19 | }; 20 | 21 | for (let i = 0; i < btnsOpenModal.length; i++) 22 | btnsOpenModal[i].addEventListener('click', openModal); 23 | 24 | btnCloseModal.addEventListener('click', closeModal); 25 | overlay.addEventListener('click', closeModal); 26 | 27 | document.addEventListener('keydown', function (e) { 28 | if (e.key === 'Escape' && !modal.classList.contains('hidden')) { 29 | closeModal(); 30 | } 31 | }); 32 | -------------------------------------------------------------------------------- /14-OOP/final/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /14-OOP/final/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Object Oriented Programming (OOP) With JavaScript 8 | 25 | 26 | 27 | 28 |

Object Oriented Programming (OOP) With JavaScript

29 | 30 | 31 | -------------------------------------------------------------------------------- /14-OOP/starter/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /14-OOP/starter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Object Oriented Programming (OOP) With JavaScript 8 | 25 | 26 | 27 | 28 |

Object Oriented Programming (OOP) With JavaScript

29 | 30 | 31 | -------------------------------------------------------------------------------- /14-OOP/starter/script.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | -------------------------------------------------------------------------------- /15-Mapty/final/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /15-Mapty/final/Mapty-architecture-final.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/15-Mapty/final/Mapty-architecture-final.png -------------------------------------------------------------------------------- /15-Mapty/final/Mapty-architecture-part-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/15-Mapty/final/Mapty-architecture-part-1.png -------------------------------------------------------------------------------- /15-Mapty/final/Mapty-flowchart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/15-Mapty/final/Mapty-flowchart.png -------------------------------------------------------------------------------- /15-Mapty/final/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/15-Mapty/final/icon.png -------------------------------------------------------------------------------- /15-Mapty/final/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/15-Mapty/final/logo.png -------------------------------------------------------------------------------- /15-Mapty/final/other.js: -------------------------------------------------------------------------------- 1 | const firstName = 'Jonas'; 2 | console.log(months); 3 | -------------------------------------------------------------------------------- /15-Mapty/final/style.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --color-brand--1: #ffb545; 3 | --color-brand--2: #00c46a; 4 | 5 | --color-dark--1: #2d3439; 6 | --color-dark--2: #42484d; 7 | --color-light--1: #aaa; 8 | --color-light--2: #ececec; 9 | --color-light--3: rgb(214, 222, 224); 10 | } 11 | 12 | * { 13 | margin: 0; 14 | padding: 0; 15 | box-sizing: inherit; 16 | } 17 | 18 | html { 19 | font-size: 62.5%; 20 | box-sizing: border-box; 21 | } 22 | 23 | body { 24 | font-family: 'Manrope', sans-serif; 25 | color: var(--color-light--2); 26 | font-weight: 400; 27 | line-height: 1.6; 28 | height: 100vh; 29 | overscroll-behavior-y: none; 30 | 31 | background-color: #fff; 32 | padding: 2.5rem; 33 | 34 | display: flex; 35 | } 36 | 37 | /* GENERAL */ 38 | a:link, 39 | a:visited { 40 | color: var(--color-brand--1); 41 | } 42 | 43 | /* SIDEBAR */ 44 | .sidebar { 45 | flex-basis: 50rem; 46 | background-color: var(--color-dark--1); 47 | padding: 3rem 5rem 4rem 5rem; 48 | display: flex; 49 | flex-direction: column; 50 | } 51 | 52 | .logo { 53 | height: 5.2rem; 54 | align-self: center; 55 | margin-bottom: 4rem; 56 | } 57 | 58 | .workouts { 59 | list-style: none; 60 | height: 77vh; 61 | overflow-y: scroll; 62 | overflow-x: hidden; 63 | } 64 | 65 | .workouts::-webkit-scrollbar { 66 | width: 0; 67 | } 68 | 69 | .workout { 70 | background-color: var(--color-dark--2); 71 | border-radius: 5px; 72 | padding: 1.5rem 2.25rem; 73 | margin-bottom: 1.75rem; 74 | cursor: pointer; 75 | 76 | display: grid; 77 | grid-template-columns: 1fr 1fr 1fr 1fr; 78 | gap: 0.75rem 1.5rem; 79 | } 80 | .workout--running { 81 | border-left: 5px solid var(--color-brand--2); 82 | } 83 | .workout--cycling { 84 | border-left: 5px solid var(--color-brand--1); 85 | } 86 | 87 | .workout__title { 88 | font-size: 1.7rem; 89 | font-weight: 600; 90 | grid-column: 1 / -1; 91 | } 92 | 93 | .workout__details { 94 | display: flex; 95 | align-items: baseline; 96 | } 97 | 98 | .workout__icon { 99 | font-size: 1.8rem; 100 | margin-right: 0.2rem; 101 | height: 0.28rem; 102 | } 103 | 104 | .workout__value { 105 | font-size: 1.5rem; 106 | margin-right: 0.5rem; 107 | } 108 | 109 | .workout__unit { 110 | font-size: 1.1rem; 111 | color: var(--color-light--1); 112 | text-transform: uppercase; 113 | font-weight: 800; 114 | } 115 | 116 | .form { 117 | background-color: var(--color-dark--2); 118 | border-radius: 5px; 119 | padding: 1.5rem 2.75rem; 120 | margin-bottom: 1.75rem; 121 | 122 | display: grid; 123 | grid-template-columns: 1fr 1fr; 124 | gap: 0.5rem 2.5rem; 125 | 126 | /* Match height and activity boxes */ 127 | height: 9.25rem; 128 | transition: all 0.5s, transform 1ms; 129 | } 130 | 131 | .form.hidden { 132 | transform: translateY(-30rem); 133 | height: 0; 134 | padding: 0 2.25rem; 135 | margin-bottom: 0; 136 | opacity: 0; 137 | } 138 | 139 | .form__row { 140 | display: flex; 141 | align-items: center; 142 | } 143 | 144 | .form__row--hidden { 145 | display: none; 146 | } 147 | 148 | .form__label { 149 | flex: 0 0 50%; 150 | font-size: 1.5rem; 151 | font-weight: 600; 152 | } 153 | 154 | .form__input { 155 | width: 100%; 156 | padding: 0.3rem 1.1rem; 157 | font-family: inherit; 158 | font-size: 1.4rem; 159 | border: none; 160 | border-radius: 3px; 161 | background-color: var(--color-light--3); 162 | transition: all 0.2s; 163 | } 164 | 165 | .form__input:focus { 166 | outline: none; 167 | background-color: #fff; 168 | } 169 | 170 | .form__btn { 171 | display: none; 172 | } 173 | 174 | .copyright { 175 | margin-top: auto; 176 | font-size: 1.3rem; 177 | text-align: center; 178 | color: var(--color-light--1); 179 | } 180 | 181 | .twitter-link:link, 182 | .twitter-link:visited { 183 | color: var(--color-light--1); 184 | transition: all 0.2s; 185 | } 186 | 187 | .twitter-link:hover, 188 | .twitter-link:active { 189 | color: var(--color-light--2); 190 | } 191 | 192 | /* MAP */ 193 | #map { 194 | flex: 1; 195 | height: 100%; 196 | background-color: var(--color-light--1); 197 | } 198 | 199 | /* Popup width is defined in JS using options */ 200 | .leaflet-popup .leaflet-popup-content-wrapper { 201 | background-color: var(--color-dark--1); 202 | color: var(--color-light--2); 203 | border-radius: 5px; 204 | padding-right: 0.6rem; 205 | } 206 | 207 | .leaflet-popup .leaflet-popup-content { 208 | font-size: 1.5rem; 209 | } 210 | 211 | .leaflet-popup .leaflet-popup-tip { 212 | background-color: var(--color-dark--1); 213 | } 214 | 215 | .running-popup .leaflet-popup-content-wrapper { 216 | border-left: 5px solid var(--color-brand--2); 217 | } 218 | .cycling-popup .leaflet-popup-content-wrapper { 219 | border-left: 5px solid var(--color-brand--1); 220 | } 221 | -------------------------------------------------------------------------------- /15-Mapty/starter/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /15-Mapty/starter/Mapty-architecture-final.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/15-Mapty/starter/Mapty-architecture-final.png -------------------------------------------------------------------------------- /15-Mapty/starter/Mapty-architecture-part-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/15-Mapty/starter/Mapty-architecture-part-1.png -------------------------------------------------------------------------------- /15-Mapty/starter/Mapty-flowchart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/15-Mapty/starter/Mapty-flowchart.png -------------------------------------------------------------------------------- /15-Mapty/starter/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/15-Mapty/starter/icon.png -------------------------------------------------------------------------------- /15-Mapty/starter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 15 | 16 | 17 | mapty // Map your workouts 18 | 19 | 20 | 120 | 121 |
122 | 123 | 124 | -------------------------------------------------------------------------------- /15-Mapty/starter/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/15-Mapty/starter/logo.png -------------------------------------------------------------------------------- /15-Mapty/starter/script.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // prettier-ignore 4 | const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; 5 | 6 | const form = document.querySelector('.form'); 7 | const containerWorkouts = document.querySelector('.workouts'); 8 | const inputType = document.querySelector('.form__input--type'); 9 | const inputDistance = document.querySelector('.form__input--distance'); 10 | const inputDuration = document.querySelector('.form__input--duration'); 11 | const inputCadence = document.querySelector('.form__input--cadence'); 12 | const inputElevation = document.querySelector('.form__input--elevation'); 13 | -------------------------------------------------------------------------------- /15-Mapty/starter/style.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --color-brand--1: #ffb545; 3 | --color-brand--2: #00c46a; 4 | 5 | --color-dark--1: #2d3439; 6 | --color-dark--2: #42484d; 7 | --color-light--1: #aaa; 8 | --color-light--2: #ececec; 9 | --color-light--3: rgb(214, 222, 224); 10 | } 11 | 12 | * { 13 | margin: 0; 14 | padding: 0; 15 | box-sizing: inherit; 16 | } 17 | 18 | html { 19 | font-size: 62.5%; 20 | box-sizing: border-box; 21 | } 22 | 23 | body { 24 | font-family: 'Manrope', sans-serif; 25 | color: var(--color-light--2); 26 | font-weight: 400; 27 | line-height: 1.6; 28 | height: 100vh; 29 | overscroll-behavior-y: none; 30 | 31 | background-color: #fff; 32 | padding: 2.5rem; 33 | 34 | display: flex; 35 | } 36 | 37 | /* GENERAL */ 38 | a:link, 39 | a:visited { 40 | color: var(--color-brand--1); 41 | } 42 | 43 | /* SIDEBAR */ 44 | .sidebar { 45 | flex-basis: 50rem; 46 | background-color: var(--color-dark--1); 47 | padding: 3rem 5rem 4rem 5rem; 48 | display: flex; 49 | flex-direction: column; 50 | } 51 | 52 | .logo { 53 | height: 5.2rem; 54 | align-self: center; 55 | margin-bottom: 4rem; 56 | } 57 | 58 | .workouts { 59 | list-style: none; 60 | height: 77vh; 61 | overflow-y: scroll; 62 | overflow-x: hidden; 63 | } 64 | 65 | .workouts::-webkit-scrollbar { 66 | width: 0; 67 | } 68 | 69 | .workout { 70 | background-color: var(--color-dark--2); 71 | border-radius: 5px; 72 | padding: 1.5rem 2.25rem; 73 | margin-bottom: 1.75rem; 74 | cursor: pointer; 75 | 76 | display: grid; 77 | grid-template-columns: 1fr 1fr 1fr 1fr; 78 | gap: 0.75rem 1.5rem; 79 | } 80 | .workout--running { 81 | border-left: 5px solid var(--color-brand--2); 82 | } 83 | .workout--cycling { 84 | border-left: 5px solid var(--color-brand--1); 85 | } 86 | 87 | .workout__title { 88 | font-size: 1.7rem; 89 | font-weight: 600; 90 | grid-column: 1 / -1; 91 | } 92 | 93 | .workout__details { 94 | display: flex; 95 | align-items: baseline; 96 | } 97 | 98 | .workout__icon { 99 | font-size: 1.8rem; 100 | margin-right: 0.2rem; 101 | height: 0.28rem; 102 | } 103 | 104 | .workout__value { 105 | font-size: 1.5rem; 106 | margin-right: 0.5rem; 107 | } 108 | 109 | .workout__unit { 110 | font-size: 1.1rem; 111 | color: var(--color-light--1); 112 | text-transform: uppercase; 113 | font-weight: 800; 114 | } 115 | 116 | .form { 117 | background-color: var(--color-dark--2); 118 | border-radius: 5px; 119 | padding: 1.5rem 2.75rem; 120 | margin-bottom: 1.75rem; 121 | 122 | display: grid; 123 | grid-template-columns: 1fr 1fr; 124 | gap: 0.5rem 2.5rem; 125 | 126 | /* Match height and activity boxes */ 127 | height: 9.25rem; 128 | transition: all 0.5s, transform 1ms; 129 | } 130 | 131 | .form.hidden { 132 | transform: translateY(-30rem); 133 | height: 0; 134 | padding: 0 2.25rem; 135 | margin-bottom: 0; 136 | opacity: 0; 137 | } 138 | 139 | .form__row { 140 | display: flex; 141 | align-items: center; 142 | } 143 | 144 | .form__row--hidden { 145 | display: none; 146 | } 147 | 148 | .form__label { 149 | flex: 0 0 50%; 150 | font-size: 1.5rem; 151 | font-weight: 600; 152 | } 153 | 154 | .form__input { 155 | width: 100%; 156 | padding: 0.3rem 1.1rem; 157 | font-family: inherit; 158 | font-size: 1.4rem; 159 | border: none; 160 | border-radius: 3px; 161 | background-color: var(--color-light--3); 162 | transition: all 0.2s; 163 | } 164 | 165 | .form__input:focus { 166 | outline: none; 167 | background-color: #fff; 168 | } 169 | 170 | .form__btn { 171 | display: none; 172 | } 173 | 174 | .copyright { 175 | margin-top: auto; 176 | font-size: 1.3rem; 177 | text-align: center; 178 | color: var(--color-light--1); 179 | } 180 | 181 | .twitter-link:link, 182 | .twitter-link:visited { 183 | color: var(--color-light--1); 184 | transition: all 0.2s; 185 | } 186 | 187 | .twitter-link:hover, 188 | .twitter-link:active { 189 | color: var(--color-light--2); 190 | } 191 | 192 | /* MAP */ 193 | #map { 194 | flex: 1; 195 | height: 100%; 196 | background-color: var(--color-light--1); 197 | } 198 | 199 | /* Popup width is defined in JS using options */ 200 | .leaflet-popup .leaflet-popup-content-wrapper { 201 | background-color: var(--color-dark--1); 202 | color: var(--color-light--2); 203 | border-radius: 5px; 204 | padding-right: 0.6rem; 205 | } 206 | 207 | .leaflet-popup .leaflet-popup-content { 208 | font-size: 1.5rem; 209 | } 210 | 211 | .leaflet-popup .leaflet-popup-tip { 212 | background-color: var(--color-dark--1); 213 | } 214 | 215 | .running-popup .leaflet-popup-content-wrapper { 216 | border-left: 5px solid var(--color-brand--2); 217 | } 218 | .cycling-popup .leaflet-popup-content-wrapper { 219 | border-left: 5px solid var(--color-brand--1); 220 | } 221 | -------------------------------------------------------------------------------- /16-Asynchronous/final/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /16-Asynchronous/final/img/img-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/16-Asynchronous/final/img/img-1.jpg -------------------------------------------------------------------------------- /16-Asynchronous/final/img/img-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/16-Asynchronous/final/img/img-2.jpg -------------------------------------------------------------------------------- /16-Asynchronous/final/img/img-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/16-Asynchronous/final/img/img-3.jpg -------------------------------------------------------------------------------- /16-Asynchronous/final/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Asynchronous JavaScript 10 | 11 | 12 |
13 |
14 | 26 |
27 | 28 |
29 |
30 | 31 | 32 | -------------------------------------------------------------------------------- /16-Asynchronous/final/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: inherit; 5 | } 6 | 7 | html { 8 | font-size: 62.5%; 9 | box-sizing: border-box; 10 | } 11 | 12 | body { 13 | font-family: system-ui; 14 | color: #555; 15 | background-color: #f7f7f7; 16 | min-height: 100vh; 17 | 18 | display: flex; 19 | align-items: center; 20 | justify-content: center; 21 | } 22 | 23 | .container { 24 | display: flex; 25 | flex-flow: column; 26 | align-items: center; 27 | } 28 | 29 | .countries { 30 | /* margin-bottom: 8rem; */ 31 | display: flex; 32 | 33 | font-size: 2rem; 34 | opacity: 0; 35 | transition: opacity 1s; 36 | } 37 | 38 | .country { 39 | background-color: #fff; 40 | box-shadow: 0 2rem 5rem 1rem rgba(0, 0, 0, 0.1); 41 | font-size: 1.8rem; 42 | width: 30rem; 43 | border-radius: 0.7rem; 44 | margin: 0 3rem; 45 | /* overflow: hidden; */ 46 | } 47 | 48 | .neighbour::before { 49 | content: 'Neighbour country'; 50 | width: 100%; 51 | position: absolute; 52 | top: -4rem; 53 | 54 | text-align: center; 55 | font-size: 1.8rem; 56 | font-weight: 600; 57 | text-transform: uppercase; 58 | color: #888; 59 | } 60 | 61 | .neighbour { 62 | transform: scale(0.8) translateY(1rem); 63 | margin-left: 0; 64 | } 65 | 66 | .country__img { 67 | width: 30rem; 68 | height: 17rem; 69 | object-fit: cover; 70 | background-color: #eee; 71 | border-top-left-radius: 0.7rem; 72 | border-top-right-radius: 0.7rem; 73 | } 74 | 75 | .country__data { 76 | padding: 2.5rem 3.75rem 3rem 3.75rem; 77 | } 78 | 79 | .country__name { 80 | font-size: 2.7rem; 81 | margin-bottom: 0.7rem; 82 | } 83 | 84 | .country__region { 85 | font-size: 1.4rem; 86 | margin-bottom: 2.5rem; 87 | text-transform: uppercase; 88 | color: #888; 89 | } 90 | 91 | .country__row:not(:last-child) { 92 | margin-bottom: 1rem; 93 | } 94 | 95 | .country__row span { 96 | display: inline-block; 97 | margin-right: 2rem; 98 | font-size: 2.4rem; 99 | } 100 | 101 | .btn-country { 102 | border: none; 103 | font-size: 2rem; 104 | padding: 2rem 5rem; 105 | border-radius: 0.7rem; 106 | color: white; 107 | background-color: orangered; 108 | cursor: pointer; 109 | } 110 | 111 | .images { 112 | display: flex; 113 | } 114 | 115 | .images img { 116 | display: block; 117 | width: 80rem; 118 | margin: 4rem; 119 | } 120 | 121 | .images img.parallel { 122 | width: 40rem; 123 | margin: 2rem; 124 | border: 3rem solid white; 125 | box-shadow: 0 2rem 5rem 1rem rgba(0, 0, 0, 0.1); 126 | } 127 | -------------------------------------------------------------------------------- /16-Asynchronous/starter/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /16-Asynchronous/starter/img/img-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/16-Asynchronous/starter/img/img-1.jpg -------------------------------------------------------------------------------- /16-Asynchronous/starter/img/img-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/16-Asynchronous/starter/img/img-2.jpg -------------------------------------------------------------------------------- /16-Asynchronous/starter/img/img-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/16-Asynchronous/starter/img/img-3.jpg -------------------------------------------------------------------------------- /16-Asynchronous/starter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Asynchronous JavaScript 10 | 11 | 12 |
13 |
14 | 26 |
27 | 28 |
29 |
30 | 31 | 32 | -------------------------------------------------------------------------------- /16-Asynchronous/starter/script.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const btn = document.querySelector('.btn-country'); 4 | const countriesContainer = document.querySelector('.countries'); 5 | 6 | /////////////////////////////////////// 7 | -------------------------------------------------------------------------------- /16-Asynchronous/starter/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: inherit; 5 | } 6 | 7 | html { 8 | font-size: 62.5%; 9 | box-sizing: border-box; 10 | } 11 | 12 | body { 13 | font-family: system-ui; 14 | color: #555; 15 | background-color: #f7f7f7; 16 | min-height: 100vh; 17 | 18 | display: flex; 19 | align-items: center; 20 | justify-content: center; 21 | } 22 | 23 | .container { 24 | display: flex; 25 | flex-flow: column; 26 | align-items: center; 27 | } 28 | 29 | .countries { 30 | /* margin-bottom: 8rem; */ 31 | display: flex; 32 | 33 | font-size: 2rem; 34 | opacity: 0; 35 | transition: opacity 1s; 36 | } 37 | 38 | .country { 39 | background-color: #fff; 40 | box-shadow: 0 2rem 5rem 1rem rgba(0, 0, 0, 0.1); 41 | font-size: 1.8rem; 42 | width: 30rem; 43 | border-radius: 0.7rem; 44 | margin: 0 3rem; 45 | /* overflow: hidden; */ 46 | } 47 | 48 | .neighbour::before { 49 | content: 'Neighbour country'; 50 | width: 100%; 51 | position: absolute; 52 | top: -4rem; 53 | 54 | text-align: center; 55 | font-size: 1.8rem; 56 | font-weight: 600; 57 | text-transform: uppercase; 58 | color: #888; 59 | } 60 | 61 | .neighbour { 62 | transform: scale(0.8) translateY(1rem); 63 | margin-left: 0; 64 | } 65 | 66 | .country__img { 67 | width: 30rem; 68 | height: 17rem; 69 | object-fit: cover; 70 | background-color: #eee; 71 | border-top-left-radius: 0.7rem; 72 | border-top-right-radius: 0.7rem; 73 | } 74 | 75 | .country__data { 76 | padding: 2.5rem 3.75rem 3rem 3.75rem; 77 | } 78 | 79 | .country__name { 80 | font-size: 2.7rem; 81 | margin-bottom: 0.7rem; 82 | } 83 | 84 | .country__region { 85 | font-size: 1.4rem; 86 | margin-bottom: 2.5rem; 87 | text-transform: uppercase; 88 | color: #888; 89 | } 90 | 91 | .country__row:not(:last-child) { 92 | margin-bottom: 1rem; 93 | } 94 | 95 | .country__row span { 96 | display: inline-block; 97 | margin-right: 2rem; 98 | font-size: 2.4rem; 99 | } 100 | 101 | .btn-country { 102 | border: none; 103 | font-size: 2rem; 104 | padding: 2rem 5rem; 105 | border-radius: 0.7rem; 106 | color: white; 107 | background-color: orangered; 108 | cursor: pointer; 109 | } 110 | 111 | .images { 112 | display: flex; 113 | } 114 | 115 | .images img { 116 | display: block; 117 | width: 80rem; 118 | margin: 4rem; 119 | } 120 | 121 | .images img.parallel { 122 | width: 40rem; 123 | margin: 2rem; 124 | border: 3rem solid white; 125 | box-shadow: 0 2rem 5rem 1rem rgba(0, 0, 0, 0.1); 126 | } 127 | -------------------------------------------------------------------------------- /17-Modern-JS-Modules-Tooling/final/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /17-Modern-JS-Modules-Tooling/final/clean.js: -------------------------------------------------------------------------------- 1 | 'strict mode'; 2 | 3 | const budget = Object.freeze([ 4 | { value: 250, description: 'Sold old TV 📺', user: 'jonas' }, 5 | { value: -45, description: 'Groceries 🥑', user: 'jonas' }, 6 | { value: 3500, description: 'Monthly salary 👩‍💻', user: 'jonas' }, 7 | { value: 300, description: 'Freelancing 👩‍💻', user: 'jonas' }, 8 | { value: -1100, description: 'New iPhone 📱', user: 'jonas' }, 9 | { value: -20, description: 'Candy 🍭', user: 'matilda' }, 10 | { value: -125, description: 'Toys 🚂', user: 'matilda' }, 11 | { value: -1800, description: 'New Laptop 💻', user: 'jonas' }, 12 | ]); 13 | 14 | const spendingLimits = Object.freeze({ 15 | jonas: 1500, 16 | matilda: 100, 17 | }); 18 | // spendingLimits.jay = 200; 19 | 20 | // const limit = spendingLimits[user] ? spendingLimits[user] : 0; 21 | const getLimit = (limits, user) => limits?.[user] ?? 0; 22 | 23 | // Pure function :D 24 | const addExpense = function ( 25 | state, 26 | limits, 27 | value, 28 | description, 29 | user = 'jonas' 30 | ) { 31 | const cleanUser = user.toLowerCase(); 32 | 33 | return value <= getLimit(limits, cleanUser) 34 | ? [...state, { value: -value, description, user: cleanUser }] 35 | : state; 36 | }; 37 | 38 | const newBudget1 = addExpense(budget, spendingLimits, 10, 'Pizza 🍕'); 39 | const newBudget2 = addExpense( 40 | newBudget1, 41 | spendingLimits, 42 | 100, 43 | 'Going to movies 🍿', 44 | 'Matilda' 45 | ); 46 | const newBudget3 = addExpense(newBudget2, spendingLimits, 200, 'Stuff', 'Jay'); 47 | 48 | // const checkExpenses2 = function (state, limits) { 49 | // return state.map(entry => { 50 | // return entry.value < -getLimit(limits, entry.user) 51 | // ? { ...entry, flag: 'limit' } 52 | // : entry; 53 | // }); 54 | // // for (const entry of newBudget3) 55 | // // if (entry.value < -getLimit(limits, entry.user)) entry.flag = 'limit'; 56 | // }; 57 | 58 | const checkExpenses = (state, limits) => 59 | state.map(entry => 60 | entry.value < -getLimit(limits, entry.user) 61 | ? { ...entry, flag: 'limit' } 62 | : entry 63 | ); 64 | 65 | const finalBudget = checkExpenses(newBudget3, spendingLimits); 66 | console.log(finalBudget); 67 | 68 | // Impure 69 | const logBigExpenses = function (state, bigLimit) { 70 | const bigExpenses = state 71 | .filter(entry => entry.value <= -bigLimit) 72 | .map(entry => entry.description.slice(-2)) 73 | .join(' / '); 74 | // .reduce((str, cur) => `${str} / ${cur.description.slice(-2)}`, ''); 75 | 76 | console.log(bigExpenses); 77 | 78 | // let output = ''; 79 | // for (const entry of budget) 80 | // output += 81 | // entry.value <= -bigLimit ? `${entry.description.slice(-2)} / ` : ''; 82 | // output = output.slice(0, -2); // Remove last '/ ' 83 | // console.log(output); 84 | }; 85 | 86 | logBigExpenses(finalBudget, 500); 87 | -------------------------------------------------------------------------------- /17-Modern-JS-Modules-Tooling/final/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Modern JavaScript Development: Modules and Tooling 11 | 26 | 27 | 28 |

Modern JavaScript Development: Modules and Tooling

29 | 30 | 31 | -------------------------------------------------------------------------------- /17-Modern-JS-Modules-Tooling/final/dist/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["node_modules/parcel/src/builtins/bundle-url.js","node_modules/parcel/src/builtins/css-loader.js"],"names":["bundleURL","getBundleURLCached","getBundleURL","Error","err","matches","stack","match","getBaseURL","url","replace","exports","bundle","require","updateLink","link","newLink","cloneNode","onload","remove","href","split","Date","now","parentNode","insertBefore","nextSibling","cssTimeout","reloadCSS","setTimeout","links","document","querySelectorAll","i","length","module"],"mappings":"AAAA,ACAA,IDAIA,ACAAY,MAAM,GDAG,ACAAC,GDAG,IAAhB,ACAoB,CAAC,cAAD,CAApB;;ADCA,ACCA,SDDSZ,ACCAa,UAAT,CAAoBC,IAApB,EAA0B,CDD1B,GAA8B;AAC5B,ACCA,MDDI,ACCAC,CDDChB,MCCM,GDDX,ACCce,EDDE,ECCE,CAACE,SAAL,EAAd;ADAEjB,IAAAA,SAAS,GAAGE,YAAY,EAAxB;AACD,ACADc,EAAAA,OAAO,CAACE,MAAR,GAAiB,YAAY;AAC3BH,IAAAA,IAAI,CAACI,MAAL;ADCF,ACAC,GAFD,MDEOnB,SAAP;AACD;ACACgB,EAAAA,OAAO,CAACI,IAAR,GAAeL,IAAI,CAACK,IAAL,CAAUC,KAAV,CAAgB,GAAhB,EAAqB,CAArB,IAA0B,GAA1B,GAAgCC,IAAI,CAACC,GAAL,EAA/C;ADEF,ACDER,EAAAA,IAAI,CAACS,EDCEtB,QCDP,CAAgBuB,GDClB,GAAwB,MCDtB,CAA6BT,OAA7B,EAAsCD,IAAI,CAACW,WAA3C;ADEA,ACDD;ADEC,MAAI;AACF,ACDJ,IAAIC,MDCM,IAAIxB,ACDA,GAAG,EDCP,EAAN,ACDJ;ADEG,GAFD,CAEE,OAAOC,GAAP,EAAY;AACZ,ACFJ,QDEQC,CCFCuB,MDEM,GAAG,ACFlB,CDEmB,ECFE,GDEGxB,GAAG,CAACE,KAAV,EAAiBC,KAAjB,CAAuB,+DAAvB,CAAd;ACDF,MAAIoB,UAAJ,EAAgB;ADEd,ACDA,QDCItB,OAAJ,EAAa;AACX,ACDH,aDCUG,UAAU,CAACH,OAAO,CAAC,CAAD,CAAR,CAAjB;AACD;AACF,ACDDsB,EAAAA,UAAU,GAAGE,UAAU,CAAC,YAAY;AAClC,QAAIC,KAAK,GAAGC,QAAQ,CAACC,gBAAT,CAA0B,wBAA1B,CAAZ;ADEF,SAAO,GAAP;AACD,ACFG,SAAK,IAAIC,CAAC,GAAG,CAAb,EAAgBA,CAAC,GAAGH,KAAK,CAACI,MAA1B,EAAkCD,CAAC,EAAnC,EAAuC;AACrC,UAAIrB,MAAM,CAACJ,UAAP,CAAkBsB,KAAK,CAACG,CAAD,CAAL,CAASb,IAA3B,MAAqCR,MAAM,CAACV,YAAP,EAAzC,EAAgE;ADGtE,ACFQY,QAAAA,CDECN,SCFS,CDElB,ACFmBsB,CDECrB,GAApB,CCFwB,CDEC,ACFAwB,CAAD,CAAN,CAAV;ADGN,ACFK,SDEE,CAAC,KAAKxB,GAAN,EAAWC,OAAX,CAAmB,sEAAnB,EAA2F,IAA3F,IAAmG,GAA1G;AACD,ACFI;;ADILC,ACFIgB,IAAAA,GDEG,CAACzB,MCFM,GAAG,GDEjB,CCFI,EDEmBD,kBAAvB;AACAU,ACFG,GATsB,EASpB,EDEE,ACXkB,CDWjBH,ACXN,UDWF,GAAqBA,UAArB;ACDC;;AAED2B,MAAM,CAACxB,OAAP,GAAiBiB,SAAjB","file":"index.js","sourceRoot":"..","sourcesContent":["var bundleURL = null;\nfunction getBundleURLCached() {\n if (!bundleURL) {\n bundleURL = getBundleURL();\n }\n\n return bundleURL;\n}\n\nfunction getBundleURL() {\n // Attempt to find the URL of the current script and use that as the base URL\n try {\n throw new Error;\n } catch (err) {\n var matches = ('' + err.stack).match(/(https?|file|ftp|chrome-extension|moz-extension):\\/\\/[^)\\n]+/g);\n if (matches) {\n return getBaseURL(matches[0]);\n }\n }\n\n return '/';\n}\n\nfunction getBaseURL(url) {\n return ('' + url).replace(/^((?:https?|file|ftp|chrome-extension|moz-extension):\\/\\/.+)\\/[^/]+$/, '$1') + '/';\n}\n\nexports.getBundleURL = getBundleURLCached;\nexports.getBaseURL = getBaseURL;\n","var bundle = require('./bundle-url');\n\nfunction updateLink(link) {\n var newLink = link.cloneNode();\n newLink.onload = function () {\n link.remove();\n };\n newLink.href = link.href.split('?')[0] + '?' + Date.now();\n link.parentNode.insertBefore(newLink, link.nextSibling);\n}\n\nvar cssTimeout = null;\nfunction reloadCSS() {\n if (cssTimeout) {\n return;\n }\n\n cssTimeout = setTimeout(function () {\n var links = document.querySelectorAll('link[rel=\"stylesheet\"]');\n for (var i = 0; i < links.length; i++) {\n if (bundle.getBaseURL(links[i].href) === bundle.getBundleURL()) {\n updateLink(links[i]);\n }\n }\n\n cssTimeout = null;\n }, 50);\n}\n\nmodule.exports = reloadCSS;\n"]} -------------------------------------------------------------------------------- /17-Modern-JS-Modules-Tooling/final/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Modern JavaScript Development: Modules and Tooling 12 | 29 | 30 | 31 |

Modern JavaScript Development: Modules and Tooling

32 | 33 | 34 | -------------------------------------------------------------------------------- /17-Modern-JS-Modules-Tooling/final/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "17-modern-js-modules-tooling", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "script.js", 6 | "scripts": { 7 | "start": "parcel index.html", 8 | "build": "parcel build index.html" 9 | }, 10 | "author": "Jonas", 11 | "license": "ISC", 12 | "dependencies": { 13 | "core-js": "^3.6.5", 14 | "leaflet": "^1.6.0", 15 | "lodash-es": "^4.17.15", 16 | "regenerator-runtime": "^0.13.7" 17 | }, 18 | "devDependencies": { 19 | "parcel": "^1.12.4" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /17-Modern-JS-Modules-Tooling/final/script.js: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////// 2 | // Exporting and Importing in ES6 Modules 3 | 4 | // Importing module 5 | // import { addToCart, totalPrice as price, tq } from './shoppingCart.js'; 6 | // addToCart('bread', 5); 7 | // console.log(price, tq); 8 | 9 | console.log('Importing module'); 10 | // console.log(shippingCost); 11 | 12 | // import * as ShoppingCart from './shoppingCart.js'; 13 | // ShoppingCart.addToCart('bread', 5); 14 | // console.log(ShoppingCart.totalPrice); 15 | 16 | // import add, { addToCart, totalPrice as price, tq } from './shoppingCart.js'; 17 | // console.log(price); 18 | 19 | import add, { cart } from './shoppingCart.js'; 20 | add('pizza', 2); 21 | add('bread', 5); 22 | add('apples', 4); 23 | 24 | console.log(cart); 25 | /* 26 | 27 | 28 | /////////////////////////////////////// 29 | // Top-Level Await (ES2022) 30 | 31 | // console.log('Start fetching'); 32 | // const res = await fetch('https://jsonplaceholder.typicode.com/posts'); 33 | // const data = await res.json(); 34 | // console.log(data); 35 | // console.log('Something'); 36 | 37 | const getLastPost = async function () { 38 | const res = await fetch('https://jsonplaceholder.typicode.com/posts'); 39 | const data = await res.json(); 40 | 41 | return { title: data.at(-1).title, text: data.at(-1).body }; 42 | }; 43 | 44 | const lastPost = getLastPost(); 45 | console.log(lastPost); 46 | 47 | // Not very clean 48 | // lastPost.then(last => console.log(last)); 49 | 50 | const lastPost2 = await getLastPost(); 51 | console.log(lastPost2); 52 | 53 | 54 | /////////////////////////////////////// 55 | // The Module Pattern 56 | 57 | const ShoppingCart2 = (function () { 58 | const cart = []; 59 | const shippingCost = 10; 60 | const totalPrice = 237; 61 | const totalQuantity = 23; 62 | 63 | const addToCart = function (product, quantity) { 64 | cart.push({ product, quantity }); 65 | console.log( 66 | `${quantity} ${product} added to cart (sipping cost is ${shippingCost})` 67 | ); 68 | }; 69 | 70 | const orderStock = function (product, quantity) { 71 | console.log(`${quantity} ${product} ordered from supplier`); 72 | }; 73 | 74 | return { 75 | addToCart, 76 | cart, 77 | totalPrice, 78 | totalQuantity, 79 | }; 80 | })(); 81 | 82 | ShoppingCart2.addToCart('apple', 4); 83 | ShoppingCart2.addToCart('pizza', 2); 84 | console.log(ShoppingCart2); 85 | console.log(ShoppingCart2.shippingCost); 86 | 87 | 88 | /////////////////////////////////////// 89 | // CommonJS Modules 90 | // Export 91 | export.addTocart = function (product, quantity) { 92 | cart.push({ product, quantity }); 93 | console.log( 94 | `${quantity} ${product} added to cart (sipping cost is ${shippingCost})` 95 | ); 96 | }; 97 | 98 | // Import 99 | const { addTocart } = require('./shoppingCart.js'); 100 | */ 101 | 102 | /////////////////////////////////////// 103 | // Introduction to NPM 104 | // import cloneDeep from './node_modules/lodash-es/cloneDeep.js'; 105 | import cloneDeep from 'lodash-es'; 106 | 107 | const state = { 108 | cart: [ 109 | { product: 'bread', quantity: 5 }, 110 | { product: 'pizza', quantity: 5 }, 111 | ], 112 | user: { loggedIn: true }, 113 | }; 114 | const stateClone = Object.assign({}, state); 115 | const stateDeepClone = cloneDeep(state); 116 | 117 | state.user.loggedIn = false; 118 | console.log(stateClone); 119 | 120 | console.log(stateDeepClone); 121 | 122 | if (module.hot) { 123 | module.hot.accept(); 124 | } 125 | 126 | class Person { 127 | #greeting = 'Hey'; 128 | constructor(name) { 129 | this.name = name; 130 | console.log(`${this.#greeting}, ${this.name}`); 131 | } 132 | } 133 | const jonas = new Person('Jonas'); 134 | 135 | console.log('Jonas' ?? null); 136 | 137 | console.log(cart.find(el => el.quantity >= 2)); 138 | Promise.resolve('TEST').then(x => console.log(x)); 139 | 140 | import 'core-js/stable'; 141 | // import 'core-js/stable/array/find'; 142 | // import 'core-js/stable/promise'; 143 | 144 | // Polifilling async functions 145 | import 'regenerator-runtime/runtime'; 146 | -------------------------------------------------------------------------------- /17-Modern-JS-Modules-Tooling/final/shoppingCart.js: -------------------------------------------------------------------------------- 1 | // Exporting module 2 | console.log('Exporting module'); 3 | 4 | // Blocking code 5 | // console.log('Start fetching users'); 6 | // await fetch('https://jsonplaceholder.typicode.com/users'); 7 | // console.log('Finish fetching users'); 8 | 9 | const shippingCost = 10; 10 | export const cart = []; 11 | 12 | export const addToCart = function (product, quantity) { 13 | cart.push({ product, quantity }); 14 | console.log(`${quantity} ${product} added to cart`); 15 | }; 16 | 17 | const totalPrice = 237; 18 | const totalQuantity = 23; 19 | 20 | export { totalPrice, totalQuantity as tq }; 21 | 22 | export default function (product, quantity) { 23 | cart.push({ product, quantity }); 24 | console.log(`${quantity} ${product} added to cart`); 25 | } 26 | -------------------------------------------------------------------------------- /17-Modern-JS-Modules-Tooling/starter/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /17-Modern-JS-Modules-Tooling/starter/clean.js: -------------------------------------------------------------------------------- 1 | var budget = [ 2 | { value: 250, description: 'Sold old TV 📺', user: 'jonas' }, 3 | { value: -45, description: 'Groceries 🥑', user: 'jonas' }, 4 | { value: 3500, description: 'Monthly salary 👩‍💻', user: 'jonas' }, 5 | { value: 300, description: 'Freelancing 👩‍💻', user: 'jonas' }, 6 | { value: -1100, description: 'New iPhone 📱', user: 'jonas' }, 7 | { value: -20, description: 'Candy 🍭', user: 'matilda' }, 8 | { value: -125, description: 'Toys 🚂', user: 'matilda' }, 9 | { value: -1800, description: 'New Laptop 💻', user: 'jonas' }, 10 | ]; 11 | 12 | var limits = { 13 | jonas: 1500, 14 | matilda: 100, 15 | }; 16 | 17 | var add = function (value, description, user) { 18 | if (!user) user = 'jonas'; 19 | user = user.toLowerCase(); 20 | 21 | var lim; 22 | if (limits[user]) { 23 | lim = limits[user]; 24 | } else { 25 | lim = 0; 26 | } 27 | 28 | if (value <= lim) { 29 | budget.push({ value: -value, description: description, user: user }); 30 | } 31 | }; 32 | add(10, 'Pizza 🍕'); 33 | add(100, 'Going to movies 🍿', 'Matilda'); 34 | add(200, 'Stuff', 'Jay'); 35 | console.log(budget); 36 | 37 | var check = function () { 38 | for (var el of budget) { 39 | var lim; 40 | if (limits[el.user]) { 41 | lim = limits[el.user]; 42 | } else { 43 | lim = 0; 44 | } 45 | 46 | if (el.value < -lim) { 47 | el.flag = 'limit'; 48 | } 49 | } 50 | }; 51 | check(); 52 | 53 | console.log(budget); 54 | 55 | var bigExpenses = function (limit) { 56 | var output = ''; 57 | for (var el of budget) { 58 | if (el.value <= -limit) { 59 | output += el.description.slice(-2) + ' / '; // Emojis are 2 chars 60 | } 61 | } 62 | output = output.slice(0, -2); // Remove last '/ ' 63 | console.log(output); 64 | }; 65 | -------------------------------------------------------------------------------- /17-Modern-JS-Modules-Tooling/starter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Modern JavaScript Development: Modules and Tooling 9 | 26 | 27 | 28 |

Modern JavaScript Development: Modules and Tooling

29 | 30 | 31 | -------------------------------------------------------------------------------- /17-Modern-JS-Modules-Tooling/starter/script.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/17-Modern-JS-Modules-Tooling/starter/script.js -------------------------------------------------------------------------------- /18-forkify/final/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .parcel-cache 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /18-forkify/final/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /18-forkify/final/README.md: -------------------------------------------------------------------------------- 1 | # forkify Project 2 | 3 | Recipe application with custom recipe uploads. 4 | -------------------------------------------------------------------------------- /18-forkify/final/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "forkify", 3 | "version": "1.0.0", 4 | "description": "Recipe application", 5 | "default": "index.html", 6 | "scripts": { 7 | "start": "parcel index.html", 8 | "build": "parcel build index.html --dist-dir ./dist" 9 | }, 10 | "author": "Jonas Schedtmann", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "parcel": "^2.0.0-beta.1", 14 | "sass": "^1.26.10" 15 | }, 16 | "dependencies": { 17 | "core-js": "^3.6.5", 18 | "fractional": "^1.0.0", 19 | "regenerator-runtime": "^0.13.7" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /18-forkify/final/src/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/18-forkify/final/src/img/favicon.png -------------------------------------------------------------------------------- /18-forkify/final/src/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/18-forkify/final/src/img/logo.png -------------------------------------------------------------------------------- /18-forkify/final/src/js/config.js: -------------------------------------------------------------------------------- 1 | export const API_URL = 'https://forkify-api.herokuapp.com/api/v2/recipes/'; 2 | export const TIMEOUT_SEC = 10; 3 | export const RES_PER_PAGE = 10; 4 | export const KEY = ''; 5 | export const MODAL_CLOSE_SEC = 2.5; 6 | -------------------------------------------------------------------------------- /18-forkify/final/src/js/controller.js: -------------------------------------------------------------------------------- 1 | import * as model from './model.js'; 2 | import { MODAL_CLOSE_SEC } from './config.js'; 3 | import recipeView from './views/recipeView.js'; 4 | import searchView from './views/searchView.js'; 5 | import resultsView from './views/resultsView.js'; 6 | import paginationView from './views/paginationView.js'; 7 | import bookmarksView from './views/bookmarksView.js'; 8 | import addRecipeView from './views/addRecipeView.js'; 9 | 10 | import 'core-js/stable'; 11 | import 'regenerator-runtime/runtime'; 12 | import { async } from 'regenerator-runtime'; 13 | 14 | const controlRecipes = async function () { 15 | try { 16 | const id = window.location.hash.slice(1); 17 | 18 | if (!id) return; 19 | recipeView.renderSpinner(); 20 | 21 | // 0) Update results view to mark selected search result 22 | resultsView.update(model.getSearchResultsPage()); 23 | 24 | // 1) Updating bookmarks view 25 | bookmarksView.update(model.state.bookmarks); 26 | 27 | // 2) Loading recipe 28 | await model.loadRecipe(id); 29 | 30 | // 3) Rendering recipe 31 | recipeView.render(model.state.recipe); 32 | } catch (err) { 33 | recipeView.renderError(); 34 | console.error(err); 35 | } 36 | }; 37 | 38 | const controlSearchResults = async function () { 39 | try { 40 | resultsView.renderSpinner(); 41 | 42 | // 1) Get search query 43 | const query = searchView.getQuery(); 44 | if (!query) return; 45 | 46 | // 2) Load search results 47 | await model.loadSearchResults(query); 48 | 49 | // 3) Render results 50 | resultsView.render(model.getSearchResultsPage()); 51 | 52 | // 4) Render initial pagination buttons 53 | paginationView.render(model.state.search); 54 | } catch (err) { 55 | console.log(err); 56 | } 57 | }; 58 | 59 | const controlPagination = function (goToPage) { 60 | // 1) Render NEW results 61 | resultsView.render(model.getSearchResultsPage(goToPage)); 62 | 63 | // 2) Render NEW pagination buttons 64 | paginationView.render(model.state.search); 65 | }; 66 | 67 | const controlServings = function (newServings) { 68 | // Update the recipe servings (in state) 69 | model.updateServings(newServings); 70 | 71 | // Update the recipe view 72 | recipeView.update(model.state.recipe); 73 | }; 74 | 75 | const controlAddBookmark = function () { 76 | // 1) Add/remove bookmark 77 | if (!model.state.recipe.bookmarked) model.addBookmark(model.state.recipe); 78 | else model.deleteBookmark(model.state.recipe.id); 79 | 80 | // 2) Update recipe view 81 | recipeView.update(model.state.recipe); 82 | 83 | // 3) Render bookmarks 84 | bookmarksView.render(model.state.bookmarks); 85 | }; 86 | 87 | const controlBookmarks = function () { 88 | bookmarksView.render(model.state.bookmarks); 89 | }; 90 | 91 | const controlAddRecipe = async function (newRecipe) { 92 | try { 93 | // Show loading spinner 94 | addRecipeView.renderSpinner(); 95 | 96 | // Upload the new recipe data 97 | await model.uploadRecipe(newRecipe); 98 | console.log(model.state.recipe); 99 | 100 | // Render recipe 101 | recipeView.render(model.state.recipe); 102 | 103 | // Success message 104 | addRecipeView.renderMessage(); 105 | 106 | // Render bookmark view 107 | bookmarksView.render(model.state.bookmarks); 108 | 109 | // Change ID in URL 110 | window.history.pushState(null, '', `#${model.state.recipe.id}`); 111 | 112 | // Close form window 113 | setTimeout(function () { 114 | addRecipeView.toggleWindow(); 115 | }, MODAL_CLOSE_SEC * 1000); 116 | } catch (err) { 117 | console.error('💥', err); 118 | addRecipeView.renderError(err.message); 119 | } 120 | }; 121 | 122 | const init = function () { 123 | bookmarksView.addHandlerRender(controlBookmarks); 124 | recipeView.addHandlerRender(controlRecipes); 125 | recipeView.addHandlerUpdateServings(controlServings); 126 | recipeView.addHandlerAddBookmark(controlAddBookmark); 127 | searchView.addHandlerSearch(controlSearchResults); 128 | paginationView.addHandlerClick(controlPagination); 129 | addRecipeView.addHandlerUpload(controlAddRecipe); 130 | }; 131 | init(); 132 | -------------------------------------------------------------------------------- /18-forkify/final/src/js/helpers.js: -------------------------------------------------------------------------------- 1 | import { async } from 'regenerator-runtime'; 2 | import { TIMEOUT_SEC } from './config.js'; 3 | 4 | const timeout = function (s) { 5 | return new Promise(function (_, reject) { 6 | setTimeout(function () { 7 | reject(new Error(`Request took too long! Timeout after ${s} second`)); 8 | }, s * 1000); 9 | }); 10 | }; 11 | 12 | export const AJAX = async function (url, uploadData = undefined) { 13 | try { 14 | const fetchPro = uploadData 15 | ? fetch(url, { 16 | method: 'POST', 17 | headers: { 18 | 'Content-Type': 'application/json', 19 | }, 20 | body: JSON.stringify(uploadData), 21 | }) 22 | : fetch(url); 23 | 24 | const res = await Promise.race([fetchPro, timeout(TIMEOUT_SEC)]); 25 | const data = await res.json(); 26 | 27 | if (!res.ok) throw new Error(`${data.message} (${res.status})`); 28 | return data; 29 | } catch (err) { 30 | throw err; 31 | } 32 | }; 33 | 34 | /* 35 | export const getJSON = async function (url) { 36 | try { 37 | const fetchPro = fetch(url); 38 | const res = await Promise.race([fetchPro, timeout(TIMEOUT_SEC)]); 39 | const data = await res.json(); 40 | 41 | if (!res.ok) throw new Error(`${data.message} (${res.status})`); 42 | return data; 43 | } catch (err) { 44 | throw err; 45 | } 46 | }; 47 | 48 | export const sendJSON = async function (url, uploadData) { 49 | try { 50 | const fetchPro = fetch(url, { 51 | method: 'POST', 52 | headers: { 53 | 'Content-Type': 'application/json', 54 | }, 55 | body: JSON.stringify(uploadData), 56 | }); 57 | 58 | const res = await Promise.race([fetchPro, timeout(TIMEOUT_SEC)]); 59 | const data = await res.json(); 60 | 61 | if (!res.ok) throw new Error(`${data.message} (${res.status})`); 62 | return data; 63 | } catch (err) { 64 | throw err; 65 | } 66 | }; 67 | */ 68 | -------------------------------------------------------------------------------- /18-forkify/final/src/js/model.js: -------------------------------------------------------------------------------- 1 | import { async } from 'regenerator-runtime'; 2 | import { API_URL, RES_PER_PAGE, KEY } from './config.js'; 3 | // import { getJSON, sendJSON } from './helpers.js'; 4 | import { AJAX } from './helpers.js'; 5 | 6 | export const state = { 7 | recipe: {}, 8 | search: { 9 | query: '', 10 | results: [], 11 | page: 1, 12 | resultsPerPage: RES_PER_PAGE, 13 | }, 14 | bookmarks: [], 15 | }; 16 | 17 | const createRecipeObject = function (data) { 18 | const { recipe } = data.data; 19 | return { 20 | id: recipe.id, 21 | title: recipe.title, 22 | publisher: recipe.publisher, 23 | sourceUrl: recipe.source_url, 24 | image: recipe.image_url, 25 | servings: recipe.servings, 26 | cookingTime: recipe.cooking_time, 27 | ingredients: recipe.ingredients, 28 | ...(recipe.key && { key: recipe.key }), 29 | }; 30 | }; 31 | 32 | export const loadRecipe = async function (id) { 33 | try { 34 | const data = await AJAX(`${API_URL}${id}?key=${KEY}`); 35 | state.recipe = createRecipeObject(data); 36 | 37 | if (state.bookmarks.some(bookmark => bookmark.id === id)) 38 | state.recipe.bookmarked = true; 39 | else state.recipe.bookmarked = false; 40 | 41 | console.log(state.recipe); 42 | } catch (err) { 43 | // Temp error handling 44 | console.error(`${err} 💥💥💥💥`); 45 | throw err; 46 | } 47 | }; 48 | 49 | export const loadSearchResults = async function (query) { 50 | try { 51 | state.search.query = query; 52 | 53 | const data = await AJAX(`${API_URL}?search=${query}&key=${KEY}`); 54 | console.log(data); 55 | 56 | state.search.results = data.data.recipes.map(rec => { 57 | return { 58 | id: rec.id, 59 | title: rec.title, 60 | publisher: rec.publisher, 61 | image: rec.image_url, 62 | ...(rec.key && { key: rec.key }), 63 | }; 64 | }); 65 | state.search.page = 1; 66 | } catch (err) { 67 | console.error(`${err} 💥💥💥💥`); 68 | throw err; 69 | } 70 | }; 71 | 72 | export const getSearchResultsPage = function (page = state.search.page) { 73 | state.search.page = page; 74 | 75 | const start = (page - 1) * state.search.resultsPerPage; // 0 76 | const end = page * state.search.resultsPerPage; // 9 77 | 78 | return state.search.results.slice(start, end); 79 | }; 80 | 81 | export const updateServings = function (newServings) { 82 | state.recipe.ingredients.forEach(ing => { 83 | ing.quantity = (ing.quantity * newServings) / state.recipe.servings; 84 | // newQt = oldQt * newServings / oldServings // 2 * 8 / 4 = 4 85 | }); 86 | 87 | state.recipe.servings = newServings; 88 | }; 89 | 90 | const persistBookmarks = function () { 91 | localStorage.setItem('bookmarks', JSON.stringify(state.bookmarks)); 92 | }; 93 | 94 | export const addBookmark = function (recipe) { 95 | // Add bookmark 96 | state.bookmarks.push(recipe); 97 | 98 | // Mark current recipe as bookmarked 99 | if (recipe.id === state.recipe.id) state.recipe.bookmarked = true; 100 | 101 | persistBookmarks(); 102 | }; 103 | 104 | export const deleteBookmark = function (id) { 105 | // Delete bookmark 106 | const index = state.bookmarks.findIndex(el => el.id === id); 107 | state.bookmarks.splice(index, 1); 108 | 109 | // Mark current recipe as NOT bookmarked 110 | if (id === state.recipe.id) state.recipe.bookmarked = false; 111 | 112 | persistBookmarks(); 113 | }; 114 | 115 | const init = function () { 116 | const storage = localStorage.getItem('bookmarks'); 117 | if (storage) state.bookmarks = JSON.parse(storage); 118 | }; 119 | init(); 120 | 121 | const clearBookmarks = function () { 122 | localStorage.clear('bookmarks'); 123 | }; 124 | // clearBookmarks(); 125 | 126 | export const uploadRecipe = async function (newRecipe) { 127 | try { 128 | const ingredients = Object.entries(newRecipe) 129 | .filter(entry => entry[0].startsWith('ingredient') && entry[1] !== '') 130 | .map(ing => { 131 | const ingArr = ing[1].split(',').map(el => el.trim()); 132 | // const ingArr = ing[1].replaceAll(' ', '').split(','); 133 | if (ingArr.length !== 3) 134 | throw new Error( 135 | 'Wrong ingredient fromat! Please use the correct format :)' 136 | ); 137 | 138 | const [quantity, unit, description] = ingArr; 139 | 140 | return { quantity: quantity ? +quantity : null, unit, description }; 141 | }); 142 | 143 | const recipe = { 144 | title: newRecipe.title, 145 | source_url: newRecipe.sourceUrl, 146 | image_url: newRecipe.image, 147 | publisher: newRecipe.publisher, 148 | cooking_time: +newRecipe.cookingTime, 149 | servings: +newRecipe.servings, 150 | ingredients, 151 | }; 152 | 153 | const data = await AJAX(`${API_URL}?key=${KEY}`, recipe); 154 | state.recipe = createRecipeObject(data); 155 | addBookmark(state.recipe); 156 | } catch (err) { 157 | throw err; 158 | } 159 | }; 160 | -------------------------------------------------------------------------------- /18-forkify/final/src/js/views/View.js: -------------------------------------------------------------------------------- 1 | import icons from 'url:../../img/icons.svg'; // Parcel 2 2 | 3 | export default class View { 4 | _data; 5 | 6 | /** 7 | * Render the received object to the DOM 8 | * @param {Object | Object[]} data The data to be rendered (e.g. recipe) 9 | * @param {boolean} [render=true] If false, create markup string instead of rendering to the DOM 10 | * @returns {undefined | string} A markup string is returned if render=false 11 | * @this {Object} View instance 12 | * @author Jonas Schmedtmann 13 | * @todo Finish implementation 14 | */ 15 | render(data, render = true) { 16 | if (!data || (Array.isArray(data) && data.length === 0)) 17 | return this.renderError(); 18 | 19 | this._data = data; 20 | const markup = this._generateMarkup(); 21 | 22 | if (!render) return markup; 23 | 24 | this._clear(); 25 | this._parentElement.insertAdjacentHTML('afterbegin', markup); 26 | } 27 | 28 | update(data) { 29 | this._data = data; 30 | const newMarkup = this._generateMarkup(); 31 | 32 | const newDOM = document.createRange().createContextualFragment(newMarkup); 33 | const newElements = Array.from(newDOM.querySelectorAll('*')); 34 | const curElements = Array.from(this._parentElement.querySelectorAll('*')); 35 | 36 | newElements.forEach((newEl, i) => { 37 | const curEl = curElements[i]; 38 | // console.log(curEl, newEl.isEqualNode(curEl)); 39 | 40 | // Updates changed TEXT 41 | if ( 42 | !newEl.isEqualNode(curEl) && 43 | newEl.firstChild?.nodeValue.trim() !== '' 44 | ) { 45 | // console.log('💥', newEl.firstChild.nodeValue.trim()); 46 | curEl.textContent = newEl.textContent; 47 | } 48 | 49 | // Updates changed ATTRIBUES 50 | if (!newEl.isEqualNode(curEl)) 51 | Array.from(newEl.attributes).forEach(attr => 52 | curEl.setAttribute(attr.name, attr.value) 53 | ); 54 | }); 55 | } 56 | 57 | _clear() { 58 | this._parentElement.innerHTML = ''; 59 | } 60 | 61 | renderSpinner() { 62 | const markup = ` 63 |
64 | 65 | 66 | 67 |
68 | `; 69 | this._clear(); 70 | this._parentElement.insertAdjacentHTML('afterbegin', markup); 71 | } 72 | 73 | renderError(message = this._errorMessage) { 74 | const markup = ` 75 |
76 |
77 | 78 | 79 | 80 |
81 |

${message}

82 |
83 | `; 84 | this._clear(); 85 | this._parentElement.insertAdjacentHTML('afterbegin', markup); 86 | } 87 | 88 | renderMessage(message = this._message) { 89 | const markup = ` 90 |
91 |
92 | 93 | 94 | 95 |
96 |

${message}

97 |
98 | `; 99 | this._clear(); 100 | this._parentElement.insertAdjacentHTML('afterbegin', markup); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /18-forkify/final/src/js/views/addRecipeView.js: -------------------------------------------------------------------------------- 1 | import View from './View.js'; 2 | import icons from 'url:../../img/icons.svg'; // Parcel 2 3 | 4 | class AddRecipeView extends View { 5 | _parentElement = document.querySelector('.upload'); 6 | _message = 'Recipe was successfully uploaded :)'; 7 | 8 | _window = document.querySelector('.add-recipe-window'); 9 | _overlay = document.querySelector('.overlay'); 10 | _btnOpen = document.querySelector('.nav__btn--add-recipe'); 11 | _btnClose = document.querySelector('.btn--close-modal'); 12 | 13 | constructor() { 14 | super(); 15 | this._addHandlerShowWindow(); 16 | this._addHandlerHideWindow(); 17 | } 18 | 19 | toggleWindow() { 20 | this._overlay.classList.toggle('hidden'); 21 | this._window.classList.toggle('hidden'); 22 | } 23 | 24 | _addHandlerShowWindow() { 25 | this._btnOpen.addEventListener('click', this.toggleWindow.bind(this)); 26 | } 27 | 28 | _addHandlerHideWindow() { 29 | this._btnClose.addEventListener('click', this.toggleWindow.bind(this)); 30 | this._overlay.addEventListener('click', this.toggleWindow.bind(this)); 31 | } 32 | 33 | addHandlerUpload(handler) { 34 | this._parentElement.addEventListener('submit', function (e) { 35 | e.preventDefault(); 36 | const dataArr = [...new FormData(this)]; 37 | const data = Object.fromEntries(dataArr); 38 | handler(data); 39 | }); 40 | } 41 | 42 | _generateMarkup() {} 43 | } 44 | 45 | export default new AddRecipeView(); 46 | -------------------------------------------------------------------------------- /18-forkify/final/src/js/views/bookmarksView.js: -------------------------------------------------------------------------------- 1 | import View from './View.js'; 2 | import previewView from './previewView.js'; 3 | import icons from 'url:../../img/icons.svg'; // Parcel 2 4 | 5 | class BookmarksView extends View { 6 | _parentElement = document.querySelector('.bookmarks__list'); 7 | _errorMessage = 'No bookmarks yet. Find a nice recipe and bookmark it ;)'; 8 | _message = ''; 9 | 10 | addHandlerRender(handler) { 11 | window.addEventListener('load', handler); 12 | } 13 | 14 | _generateMarkup() { 15 | return this._data 16 | .map(bookmark => previewView.render(bookmark, false)) 17 | .join(''); 18 | } 19 | } 20 | 21 | export default new BookmarksView(); 22 | -------------------------------------------------------------------------------- /18-forkify/final/src/js/views/paginationView.js: -------------------------------------------------------------------------------- 1 | import View from './View.js'; 2 | import icons from 'url:../../img/icons.svg'; // Parcel 2 3 | 4 | class PaginationView extends View { 5 | _parentElement = document.querySelector('.pagination'); 6 | 7 | addHandlerClick(handler) { 8 | this._parentElement.addEventListener('click', function (e) { 9 | const btn = e.target.closest('.btn--inline'); 10 | if (!btn) return; 11 | 12 | const goToPage = +btn.dataset.goto; 13 | handler(goToPage); 14 | }); 15 | } 16 | 17 | _generateMarkup() { 18 | const curPage = this._data.page; 19 | const numPages = Math.ceil( 20 | this._data.results.length / this._data.resultsPerPage 21 | ); 22 | 23 | // Page 1, and there are other pages 24 | if (curPage === 1 && numPages > 1) { 25 | return ` 26 | 34 | `; 35 | } 36 | 37 | // Last page 38 | if (curPage === numPages && numPages > 1) { 39 | return ` 40 | 48 | `; 49 | } 50 | 51 | // Other page 52 | if (curPage < numPages) { 53 | return ` 54 | 62 | 70 | `; 71 | } 72 | 73 | // Page 1, and there are NO other pages 74 | return ''; 75 | } 76 | } 77 | 78 | export default new PaginationView(); 79 | -------------------------------------------------------------------------------- /18-forkify/final/src/js/views/previewView.js: -------------------------------------------------------------------------------- 1 | import View from './View.js'; 2 | import icons from 'url:../../img/icons.svg'; // Parcel 2 3 | 4 | class PreviewView extends View { 5 | _parentElement = ''; 6 | 7 | _generateMarkup() { 8 | const id = window.location.hash.slice(1); 9 | 10 | return ` 11 |
  • 12 | 15 |
    16 | ${this._data.title} 17 |
    18 |
    19 |

    ${this._data.title}

    20 |

    ${this._data.publisher}

    21 |
    24 | 25 | 26 | 27 |
    28 |
    29 |
    30 |
  • 31 | `; 32 | } 33 | } 34 | 35 | export default new PreviewView(); 36 | -------------------------------------------------------------------------------- /18-forkify/final/src/js/views/recipeView.js: -------------------------------------------------------------------------------- 1 | import View from './View.js'; 2 | 3 | // import icons from '../img/icons.svg'; // Parcel 1 4 | import icons from 'url:../../img/icons.svg'; // Parcel 2 5 | import { Fraction } from 'fractional'; 6 | 7 | class RecipeView extends View { 8 | _parentElement = document.querySelector('.recipe'); 9 | _errorMessage = 'We could not find that recipe. Please try another one!'; 10 | _message = ''; 11 | 12 | addHandlerRender(handler) { 13 | ['hashchange', 'load'].forEach(ev => window.addEventListener(ev, handler)); 14 | } 15 | 16 | addHandlerUpdateServings(handler) { 17 | this._parentElement.addEventListener('click', function (e) { 18 | const btn = e.target.closest('.btn--update-servings'); 19 | if (!btn) return; 20 | const { updateTo } = btn.dataset; 21 | if (+updateTo > 0) handler(+updateTo); 22 | }); 23 | } 24 | 25 | addHandlerAddBookmark(handler) { 26 | this._parentElement.addEventListener('click', function (e) { 27 | const btn = e.target.closest('.btn--bookmark'); 28 | if (!btn) return; 29 | handler(); 30 | }); 31 | } 32 | 33 | _generateMarkup() { 34 | return ` 35 |
    36 | ${
 37 |       this._data.title
 38 |     } 39 |

    40 | ${this._data.title} 41 |

    42 |
    43 | 44 |
    45 |
    46 | 47 | 48 | 49 | ${ 50 | this._data.cookingTime 51 | } 52 | minutes 53 |
    54 |
    55 | 56 | 57 | 58 | ${ 59 | this._data.servings 60 | } 61 | servings 62 | 63 |
    64 | 71 | 78 |
    79 |
    80 | 81 |
    82 | 83 | 84 | 85 |
    86 | 93 |
    94 | 95 |
    96 |

    Recipe ingredients

    97 |
    100 | 101 |
    102 |

    How to cook it

    103 |

    104 | This recipe was carefully designed and tested by 105 | ${ 106 | this._data.publisher 107 | }. Please check out 108 | directions at their website. 109 |

    110 | 115 | Directions 116 | 117 | 118 | 119 | 120 |
    121 | `; 122 | } 123 | 124 | _generateMarkupIngredient(ing) { 125 | return ` 126 |
  • 127 | 128 | 129 | 130 |
    ${ 131 | ing.quantity ? new Fraction(ing.quantity).toString() : '' 132 | }
    133 |
    134 | ${ing.unit} 135 | ${ing.description} 136 |
    137 |
  • 138 | `; 139 | } 140 | } 141 | 142 | export default new RecipeView(); 143 | -------------------------------------------------------------------------------- /18-forkify/final/src/js/views/resultsView.js: -------------------------------------------------------------------------------- 1 | import View from './View.js'; 2 | import previewView from './previewView.js'; 3 | import icons from 'url:../../img/icons.svg'; // Parcel 2 4 | 5 | class ResultsView extends View { 6 | _parentElement = document.querySelector('.results'); 7 | _errorMessage = 'No recipes found for your query! Please try again ;)'; 8 | _message = ''; 9 | 10 | _generateMarkup() { 11 | return this._data.map(result => previewView.render(result, false)).join(''); 12 | } 13 | } 14 | 15 | export default new ResultsView(); 16 | -------------------------------------------------------------------------------- /18-forkify/final/src/js/views/searchView.js: -------------------------------------------------------------------------------- 1 | class SearchView { 2 | _parentEl = document.querySelector('.search'); 3 | 4 | getQuery() { 5 | const query = this._parentEl.querySelector('.search__field').value; 6 | this._clearInput(); 7 | return query; 8 | } 9 | 10 | _clearInput() { 11 | this._parentEl.querySelector('.search__field').value = ''; 12 | } 13 | 14 | addHandlerSearch(handler) { 15 | this._parentEl.addEventListener('submit', function (e) { 16 | e.preventDefault(); 17 | handler(); 18 | }); 19 | } 20 | } 21 | 22 | export default new SearchView(); 23 | -------------------------------------------------------------------------------- /18-forkify/final/src/sass/_base.scss: -------------------------------------------------------------------------------- 1 | // $color-primary: #f59a83; 2 | $color-primary: #f38e82; 3 | $color-grad-1: #fbdb89; 4 | $color-grad-2: #f48982; 5 | 6 | $color-grey-light-1: #f9f5f3; // Light background 7 | $color-grey-light-2: #f2efee; // Light lines 8 | $color-grey-light-3: #d3c7c3; // Light text (placeholder) 9 | $color-grey-dark-1: #615551; // Normal text 10 | $color-grey-dark-2: #918581; // Lighter text 11 | 12 | $gradient: linear-gradient(to right bottom, $color-grad-1, $color-grad-2); 13 | 14 | $bp-large: 78.15em; // 1250px 15 | $bp-medium: 61.25em; // 980px 16 | $bp-small: 37.5em; // 600px 17 | $bp-smallest: 31.25em; // 500px 18 | 19 | * { 20 | margin: 0; 21 | padding: 0; 22 | } 23 | 24 | *, 25 | *::before, 26 | *::after { 27 | box-sizing: inherit; 28 | } 29 | 30 | html { 31 | box-sizing: border-box; 32 | font-size: 62.5%; 33 | 34 | @media only screen and (max-width: $bp-medium) { 35 | font-size: 50%; 36 | } 37 | } 38 | 39 | body { 40 | font-family: 'Nunito Sans', sans-serif; 41 | font-weight: 400; 42 | line-height: 1.6; 43 | color: $color-grey-dark-1; 44 | background-image: $gradient; 45 | background-size: cover; 46 | background-repeat: no-repeat; 47 | min-height: calc(100vh - 2 * 4vw); 48 | } 49 | 50 | .container { 51 | max-width: 120rem; 52 | min-height: 117rem; 53 | margin: 4vw auto; 54 | background-color: #fff; 55 | border-radius: 9px; 56 | overflow: hidden; 57 | box-shadow: 0 2rem 6rem 0.5rem rgba($color-grey-dark-1, 0.2); 58 | 59 | display: grid; 60 | grid-template-rows: 10rem minmax(100rem, auto); 61 | grid-template-columns: 1fr 2fr; 62 | grid-template-areas: 63 | 'head head' 64 | 'list recipe'; 65 | 66 | @media only screen and (max-width: $bp-large) { 67 | max-width: 100%; 68 | margin: 0; 69 | border-radius: 0; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /18-forkify/final/src/sass/_components.scss: -------------------------------------------------------------------------------- 1 | %btn { 2 | background-image: $gradient; 3 | border-radius: 10rem; 4 | border: none; 5 | text-transform: uppercase; 6 | color: #fff; 7 | cursor: pointer; 8 | display: flex; 9 | align-items: center; 10 | transition: all 0.2s; 11 | 12 | &:hover { 13 | transform: scale(1.05); 14 | } 15 | 16 | &:focus { 17 | outline: none; 18 | } 19 | 20 | & > *:first-child { 21 | margin-right: 1rem; 22 | } 23 | } 24 | 25 | .btn { 26 | @extend %btn; 27 | 28 | padding: 1.5rem 4rem; 29 | font-size: 1.5rem; 30 | font-weight: 600; 31 | 32 | svg { 33 | height: 2.25rem; 34 | width: 2.25rem; 35 | fill: currentColor; 36 | } 37 | } 38 | 39 | .btn--small { 40 | &, 41 | &:link, 42 | &:visited { 43 | @extend %btn; 44 | 45 | font-size: 1.4rem; 46 | font-weight: 600; 47 | padding: 1.25rem 2.25rem; 48 | text-decoration: none; 49 | 50 | svg { 51 | height: 1.75rem; 52 | width: 1.75rem; 53 | fill: currentColor; 54 | } 55 | } 56 | } 57 | 58 | .btn--inline { 59 | color: $color-primary; 60 | font-size: 1.3rem; 61 | font-weight: 600; 62 | border: none; 63 | background-color: $color-grey-light-1; 64 | padding: 0.8rem 1.2rem; 65 | border-radius: 10rem; 66 | cursor: pointer; 67 | 68 | display: flex; 69 | align-items: center; 70 | transition: all 0.2s; 71 | 72 | svg { 73 | height: 1.6rem; 74 | width: 1.6rem; 75 | fill: currentColor; 76 | margin: 0 0.2rem; 77 | } 78 | 79 | span { 80 | margin: 0 0.4rem; 81 | } 82 | 83 | &:hover { 84 | color: $color-grad-2; 85 | background-color: $color-grey-light-2; 86 | } 87 | 88 | &:focus { 89 | outline: none; 90 | } 91 | } 92 | 93 | .btn--round { 94 | background-image: $gradient; 95 | border-radius: 50%; 96 | border: none; 97 | cursor: pointer; 98 | height: 4.5rem; 99 | width: 4.5rem; 100 | // margin-left: auto; 101 | transition: all 0.2s; 102 | 103 | display: flex; 104 | align-items: center; 105 | justify-content: center; 106 | 107 | &:hover { 108 | transform: scale(1.07); 109 | } 110 | 111 | &:focus { 112 | outline: none; 113 | } 114 | 115 | svg { 116 | height: 2.5rem; 117 | width: 2.5rem; 118 | fill: #fff; 119 | } 120 | } 121 | 122 | .btn--tiny { 123 | height: 2rem; 124 | width: 2rem; 125 | border: none; 126 | background: none; 127 | cursor: pointer; 128 | 129 | svg { 130 | height: 100%; 131 | width: 100%; 132 | fill: $color-primary; 133 | transition: all 0.3s; 134 | } 135 | 136 | &:focus { 137 | outline: none; 138 | } 139 | 140 | &:hover svg { 141 | fill: $color-grad-2; 142 | transform: translateY(-1px); 143 | } 144 | 145 | &:active svg { 146 | fill: $color-grad-2; 147 | transform: translateY(0); 148 | } 149 | 150 | &:not(:last-child) { 151 | margin-right: 0.3rem; 152 | } 153 | } 154 | 155 | .heading--2 { 156 | font-size: 2rem; 157 | font-weight: 700; 158 | color: $color-primary; 159 | text-transform: uppercase; 160 | margin-bottom: 2.5rem; 161 | text-align: center; 162 | // transform: skewY(-3deg); 163 | } 164 | 165 | .link:link, 166 | .link:visited { 167 | color: $color-grey-dark-2; 168 | } 169 | 170 | .spinner { 171 | margin: 5rem auto; 172 | text-align: center; 173 | 174 | svg { 175 | height: 6rem; 176 | width: 6rem; 177 | fill: $color-primary; 178 | animation: rotate 2s infinite linear; 179 | } 180 | } 181 | 182 | @keyframes rotate { 183 | 0% { 184 | transform: rotate(0); 185 | } 186 | 187 | 100% { 188 | transform: rotate(360deg); 189 | } 190 | } 191 | 192 | .message, 193 | .error { 194 | max-width: 40rem; 195 | margin: 0 auto; 196 | padding: 5rem 4rem; 197 | 198 | display: flex; 199 | 200 | svg { 201 | height: 3rem; 202 | width: 3rem; 203 | fill: $color-primary; 204 | transform: translateY(-0.3rem); 205 | } 206 | 207 | p { 208 | margin-left: 1.5rem; 209 | font-size: 1.8rem; 210 | line-height: 1.5; 211 | font-weight: 600; 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /18-forkify/final/src/sass/_header.scss: -------------------------------------------------------------------------------- 1 | .header { 2 | grid-area: head; 3 | background-color: $color-grey-light-1; 4 | display: flex; 5 | align-items: center; 6 | justify-content: space-between; 7 | 8 | &__logo { 9 | margin-left: 4rem; 10 | height: 4.6rem; 11 | display: block; 12 | } 13 | } 14 | 15 | .search { 16 | background-color: #fff; 17 | border-radius: 10rem; 18 | display: flex; 19 | align-items: center; 20 | padding-left: 3rem; 21 | transition: all 0.3s; 22 | 23 | &:focus-within { 24 | transform: translateY(-2px); 25 | box-shadow: 0 0.7rem 3rem rgba($color-grey-dark-1, 0.08); 26 | } 27 | 28 | &__field { 29 | border: none; 30 | background: none; 31 | font-family: inherit; 32 | color: inherit; 33 | font-size: 1.7rem; 34 | width: 30rem; 35 | 36 | &:focus { 37 | outline: none; 38 | } 39 | 40 | &::placeholder { 41 | color: $color-grey-light-3; 42 | } 43 | 44 | @media only screen and (max-width: $bp-medium) { 45 | width: auto; 46 | 47 | &::placeholder { 48 | color: white; 49 | } 50 | } 51 | } 52 | 53 | &__btn { 54 | font-weight: 600; 55 | font-family: inherit; 56 | } 57 | } 58 | 59 | .nav { 60 | align-self: stretch; 61 | margin-right: 2.5rem; 62 | 63 | &__list { 64 | list-style: none; 65 | display: flex; 66 | height: 100%; 67 | } 68 | 69 | &__item { 70 | position: relative; 71 | } 72 | 73 | &__btn { 74 | height: 100%; 75 | font-family: inherit; 76 | color: inherit; 77 | font-size: 1.4rem; 78 | font-weight: 700; 79 | text-transform: uppercase; 80 | background: none; 81 | border: none; 82 | cursor: pointer; 83 | padding: 0 1.5rem; 84 | transition: all 0.3s; 85 | 86 | display: flex; 87 | align-items: center; 88 | 89 | svg { 90 | height: 2.4rem; 91 | width: 2.4rem; 92 | fill: $color-primary; 93 | margin-right: 0.7rem; 94 | transform: translateY(-1px); 95 | } 96 | 97 | &:focus { 98 | outline: none; 99 | } 100 | 101 | &:hover { 102 | background-color: $color-grey-light-2; 103 | } 104 | } 105 | } 106 | 107 | .bookmarks { 108 | padding: 1rem 0; 109 | position: absolute; 110 | // right: 0; 111 | right: -2.5rem; 112 | z-index: 10; 113 | width: 40rem; 114 | background-color: #fff; 115 | box-shadow: 0 0.8rem 5rem 2rem rgba($color-grey-dark-1, 0.1); 116 | 117 | visibility: hidden; 118 | opacity: 0; 119 | transition: all 0.5s 0.2s; 120 | 121 | &__list { 122 | list-style: none; 123 | } 124 | 125 | &__field { 126 | cursor: pointer; 127 | padding: 0 4rem; 128 | 129 | display: flex; 130 | align-items: center; 131 | height: 100%; 132 | transition: all 0.3s; 133 | 134 | &:hover { 135 | background-color: $color-grey-light-2; 136 | } 137 | } 138 | 139 | &:hover, 140 | .nav__btn--bookmarks:hover + & { 141 | visibility: visible; 142 | opacity: 1; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /18-forkify/final/src/sass/_preview.scss: -------------------------------------------------------------------------------- 1 | .preview { 2 | &__link { 3 | &:link, 4 | &:visited { 5 | display: flex; 6 | align-items: center; 7 | padding: 1.5rem 3.25rem; 8 | transition: all 0.3s; 9 | border-right: 1px solid #fff; 10 | text-decoration: none; 11 | } 12 | 13 | &:hover { 14 | background-color: $color-grey-light-1; 15 | transform: translateY(-2px); 16 | } 17 | 18 | &--active { 19 | background-color: $color-grey-light-1; 20 | } 21 | } 22 | 23 | &__fig { 24 | flex: 0 0 5.8rem; 25 | border-radius: 50%; 26 | overflow: hidden; 27 | height: 5.8rem; 28 | margin-right: 2rem; 29 | position: relative; 30 | backface-visibility: hidden; 31 | 32 | &::before { 33 | content: ''; 34 | display: block; 35 | height: 100%; 36 | width: 100%; 37 | position: absolute; 38 | top: 0; 39 | left: 0; 40 | background-image: linear-gradient( 41 | to right bottom, 42 | $color-grad-1, 43 | $color-grad-2 44 | ); 45 | opacity: 0.4; 46 | } 47 | 48 | img { 49 | display: block; 50 | width: 100%; 51 | height: 100%; 52 | object-fit: cover; 53 | transition: all 0.3s; 54 | } 55 | } 56 | 57 | &__data { 58 | display: grid; 59 | width: 100%; 60 | grid-template-columns: 1fr 2rem; 61 | row-gap: 0.1rem; 62 | align-items: center; 63 | } 64 | 65 | &__title { 66 | grid-column: 1/-1; 67 | font-size: 1.45rem; 68 | color: $color-primary; 69 | text-transform: uppercase; 70 | font-weight: 600; 71 | 72 | // This is how text is truncated! 73 | text-overflow: ellipsis; 74 | max-width: 25rem; 75 | white-space: nowrap; 76 | overflow: hidden; 77 | } 78 | 79 | &__publisher { 80 | font-size: 1.15rem; 81 | color: $color-grey-dark-2; 82 | text-transform: uppercase; 83 | font-weight: 600; 84 | } 85 | 86 | &__user-generated { 87 | background-color: darken($color-grey-light-2, 2%); 88 | 89 | display: flex; 90 | align-items: center; 91 | justify-content: center; 92 | height: 2rem; 93 | width: 2rem; 94 | border-radius: 10rem; 95 | 96 | margin-left: auto; 97 | margin-right: 1.75rem; 98 | 99 | svg { 100 | height: 1.2rem; 101 | width: 1.2rem; 102 | fill: $color-primary; 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /18-forkify/final/src/sass/_recipe.scss: -------------------------------------------------------------------------------- 1 | .recipe { 2 | background-color: $color-grey-light-1; 3 | 4 | /////////// 5 | // FIGURE 6 | &__fig { 7 | height: 32rem; 8 | position: relative; 9 | // transform: scale(1.04) translateY(-1px); 10 | transform-origin: top; 11 | 12 | &::before { 13 | content: ''; 14 | display: block; 15 | height: 100%; 16 | width: 100%; 17 | position: absolute; 18 | top: 0; 19 | left: 0; 20 | background-image: linear-gradient( 21 | to right bottom, 22 | $color-grad-1, 23 | $color-grad-2 24 | ); 25 | opacity: 0.6; 26 | } 27 | } 28 | 29 | &__img { 30 | width: 100%; 31 | display: block; 32 | height: 100%; 33 | object-fit: cover; 34 | } 35 | 36 | &__title { 37 | position: absolute; 38 | bottom: 0; 39 | left: 50%; 40 | transform: translate(-50%, 20%) skewY(-6deg); 41 | color: #fff; 42 | font-weight: 700; 43 | font-size: 3.25rem; 44 | text-transform: uppercase; 45 | width: 50%; 46 | line-height: 1.95; 47 | text-align: center; 48 | 49 | span { 50 | -webkit-box-decoration-break: clone; 51 | box-decoration-break: clone; 52 | padding: 1.3rem 2rem; 53 | background-image: linear-gradient( 54 | to right bottom, 55 | $color-grad-1, 56 | $color-grad-2 57 | ); 58 | } 59 | 60 | @media only screen and (max-width: $bp-medium) { 61 | width: 70%; 62 | } 63 | } 64 | 65 | /////////// 66 | // DETAILS 67 | &__details { 68 | display: flex; 69 | align-items: center; 70 | padding: 7.5rem 8rem 3.5rem 8rem; 71 | } 72 | 73 | &__info { 74 | font-size: 1.65rem; 75 | text-transform: uppercase; 76 | display: flex; 77 | align-items: center; 78 | 79 | &:not(:last-child) { 80 | margin-right: 4.5rem; 81 | } 82 | } 83 | 84 | &__info-icon { 85 | height: 2.35rem; 86 | width: 2.35rem; 87 | fill: $color-primary; 88 | margin-right: 1.15rem; 89 | } 90 | 91 | &__info-data { 92 | margin-right: 0.5rem; 93 | font-weight: 700; 94 | } 95 | 96 | &__info-buttons { 97 | display: flex; 98 | margin-left: 1.6rem; 99 | transform: translateY(-1px); 100 | } 101 | 102 | &__user-generated { 103 | background-color: darken($color-grey-light-2, 2%); 104 | 105 | display: flex; 106 | align-items: center; 107 | justify-content: center; 108 | height: 4rem; 109 | width: 4rem; 110 | border-radius: 10rem; 111 | 112 | margin-left: auto; 113 | margin-right: 1.75rem; 114 | 115 | svg { 116 | height: 2.25rem; 117 | width: 2.25rem; 118 | fill: $color-primary; 119 | } 120 | } 121 | 122 | /////////// 123 | // INGREDIENTS 124 | &__ingredients { 125 | padding: 5rem 8rem; 126 | font-size: 1.6rem; 127 | line-height: 1.4; 128 | background-color: $color-grey-light-2; 129 | display: flex; 130 | flex-direction: column; 131 | align-items: center; 132 | } 133 | 134 | &__ingredient-list { 135 | display: grid; 136 | grid-template-columns: 1fr 1fr; 137 | gap: 2.5rem 3rem; 138 | list-style: none; 139 | } 140 | 141 | &__ingredient { 142 | display: flex; 143 | } 144 | 145 | &__icon { 146 | height: 2rem; 147 | width: 2rem; 148 | fill: $color-primary; 149 | margin-right: 1.1rem; 150 | flex: 0 0 auto; 151 | margin-top: 0.1rem; 152 | } 153 | 154 | &__quantity { 155 | margin-right: 0.5rem; 156 | flex: 0 0 auto; 157 | } 158 | 159 | /////////// 160 | // DIRECTIONS 161 | &__directions { 162 | padding: 5rem 10rem; 163 | padding-bottom: 5rem; 164 | display: flex; 165 | flex-direction: column; 166 | align-items: center; 167 | } 168 | 169 | &__directions-text { 170 | font-size: 1.7rem; 171 | text-align: center; 172 | margin-bottom: 3.5rem; 173 | color: $color-grey-dark-2; 174 | } 175 | 176 | &__publisher { 177 | font-weight: 700; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /18-forkify/final/src/sass/_searchResults.scss: -------------------------------------------------------------------------------- 1 | .search-results { 2 | padding: 3rem 0; 3 | display: flex; 4 | flex-direction: column; 5 | } 6 | 7 | .results { 8 | list-style: none; 9 | margin-bottom: 2rem; 10 | } 11 | 12 | .pagination { 13 | margin-top: auto; 14 | padding: 0 3.5rem; 15 | 16 | &::after { 17 | content: ''; 18 | display: table; 19 | clear: both; 20 | } 21 | 22 | &__btn { 23 | &--prev { 24 | float: left; 25 | } 26 | &--next { 27 | float: right; 28 | } 29 | } 30 | } 31 | 32 | .copyright { 33 | color: $color-grey-dark-2; 34 | font-size: 1.2rem; 35 | padding: 0 3.5rem; 36 | margin-top: 4rem; 37 | 38 | .twitter-link:link, 39 | .twitter-link:visited { 40 | color: $color-grey-dark-2; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /18-forkify/final/src/sass/_upload.scss: -------------------------------------------------------------------------------- 1 | .add-recipe-window { 2 | position: fixed; 3 | top: 50%; 4 | left: 50%; 5 | transform: translate(-50%, -50%); 6 | width: 100rem; 7 | background-color: white; 8 | border-radius: 9px; 9 | 10 | padding: 5rem 6rem; 11 | box-shadow: 0 4rem 6rem rgba(0, 0, 0, 0.25); 12 | z-index: 1000; 13 | transition: all 0.5s; 14 | 15 | .btn--close-modal { 16 | font-family: inherit; 17 | color: inherit; 18 | position: absolute; 19 | top: 0.5rem; 20 | right: 1.6rem; 21 | font-size: 3.5rem; 22 | cursor: pointer; 23 | border: none; 24 | background: none; 25 | } 26 | } 27 | 28 | .overlay { 29 | position: fixed; 30 | top: 0; 31 | left: 0; 32 | width: 100%; 33 | height: 100%; 34 | background-color: rgba(0, 0, 0, 0.4); 35 | backdrop-filter: blur(4px); 36 | z-index: 100; 37 | transition: all 0.5s; 38 | } 39 | 40 | .hidden { 41 | visibility: hidden; 42 | opacity: 0; 43 | } 44 | 45 | .upload { 46 | display: grid; 47 | grid-template-columns: 1fr 1fr; 48 | gap: 4rem 6rem; 49 | 50 | &__column { 51 | display: grid; 52 | grid-template-columns: 1fr 2.8fr; 53 | align-items: center; 54 | gap: 1.5rem; 55 | 56 | & label { 57 | font-size: 1.5rem; 58 | font-weight: 600; 59 | color: inherit; 60 | } 61 | 62 | & input { 63 | font-size: 1.5rem; 64 | padding: 0.8rem 1rem; 65 | border: 1px solid #ddd; 66 | border-radius: 0.5rem; 67 | transition: all 0.2s; 68 | 69 | &::placeholder { 70 | color: $color-grey-light-3; 71 | } 72 | 73 | &:focus { 74 | outline: none; 75 | border: 1px solid $color-primary; 76 | background-color: $color-grey-light-1; 77 | } 78 | } 79 | 80 | & button { 81 | grid-column: 1 / span 2; 82 | justify-self: center; 83 | margin-top: 1rem; 84 | } 85 | } 86 | 87 | &__heading { 88 | font-size: 2.25rem; 89 | font-weight: 700; 90 | text-transform: uppercase; 91 | margin-bottom: 1rem; 92 | grid-column: 1/-1; 93 | } 94 | 95 | &__btn { 96 | grid-column: 1 / -1; 97 | justify-self: center; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /18-forkify/final/src/sass/main.scss: -------------------------------------------------------------------------------- 1 | @import 'base'; 2 | @import 'components'; 3 | @import 'header'; 4 | @import 'preview'; 5 | @import 'searchResults'; 6 | @import 'recipe'; 7 | @import 'upload'; 8 | -------------------------------------------------------------------------------- /18-forkify/starter/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /18-forkify/starter/forkify-architecture-recipe-loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/18-forkify/starter/forkify-architecture-recipe-loading.png -------------------------------------------------------------------------------- /18-forkify/starter/forkify-flowchart-part-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/18-forkify/starter/forkify-flowchart-part-1.png -------------------------------------------------------------------------------- /18-forkify/starter/forkify-flowchart-part-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/18-forkify/starter/forkify-flowchart-part-2.png -------------------------------------------------------------------------------- /18-forkify/starter/forkify-flowchart-part-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/18-forkify/starter/forkify-flowchart-part-3.png -------------------------------------------------------------------------------- /18-forkify/starter/src/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/18-forkify/starter/src/img/favicon.png -------------------------------------------------------------------------------- /18-forkify/starter/src/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/18-forkify/starter/src/img/logo.png -------------------------------------------------------------------------------- /18-forkify/starter/src/js/controller.js: -------------------------------------------------------------------------------- 1 | const recipeContainer = document.querySelector('.recipe'); 2 | 3 | const timeout = function (s) { 4 | return new Promise(function (_, reject) { 5 | setTimeout(function () { 6 | reject(new Error(`Request took too long! Timeout after ${s} second`)); 7 | }, s * 1000); 8 | }); 9 | }; 10 | 11 | // https://forkify-api.herokuapp.com/v2 12 | 13 | /////////////////////////////////////// 14 | -------------------------------------------------------------------------------- /18-forkify/starter/src/sass/_base.scss: -------------------------------------------------------------------------------- 1 | // $color-primary: #f59a83; 2 | $color-primary: #f38e82; 3 | $color-grad-1: #fbdb89; 4 | $color-grad-2: #f48982; 5 | 6 | $color-grey-light-1: #f9f5f3; // Light background 7 | $color-grey-light-2: #f2efee; // Light lines 8 | $color-grey-light-3: #d3c7c3; // Light text (placeholder) 9 | $color-grey-dark-1: #615551; // Normal text 10 | $color-grey-dark-2: #918581; // Lighter text 11 | 12 | $gradient: linear-gradient(to right bottom, $color-grad-1, $color-grad-2); 13 | 14 | $bp-large: 78.15em; // 1250px 15 | $bp-medium: 61.25em; // 980px 16 | $bp-small: 37.5em; // 600px 17 | $bp-smallest: 31.25em; // 500px 18 | 19 | * { 20 | margin: 0; 21 | padding: 0; 22 | } 23 | 24 | *, 25 | *::before, 26 | *::after { 27 | box-sizing: inherit; 28 | } 29 | 30 | html { 31 | box-sizing: border-box; 32 | font-size: 62.5%; 33 | 34 | @media only screen and (max-width: $bp-medium) { 35 | font-size: 50%; 36 | } 37 | } 38 | 39 | body { 40 | font-family: 'Nunito Sans', sans-serif; 41 | font-weight: 400; 42 | line-height: 1.6; 43 | color: $color-grey-dark-1; 44 | background-image: $gradient; 45 | background-size: cover; 46 | background-repeat: no-repeat; 47 | min-height: calc(100vh - 2 * 4vw); 48 | } 49 | 50 | .container { 51 | max-width: 120rem; 52 | min-height: 117rem; 53 | margin: 4vw auto; 54 | background-color: #fff; 55 | border-radius: 9px; 56 | overflow: hidden; 57 | box-shadow: 0 2rem 6rem 0.5rem rgba($color-grey-dark-1, 0.2); 58 | 59 | display: grid; 60 | grid-template-rows: 10rem minmax(100rem, auto); 61 | grid-template-columns: 1fr 2fr; 62 | grid-template-areas: 63 | 'head head' 64 | 'list recipe'; 65 | 66 | @media only screen and (max-width: $bp-large) { 67 | max-width: 100%; 68 | margin: 0; 69 | border-radius: 0; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /18-forkify/starter/src/sass/_components.scss: -------------------------------------------------------------------------------- 1 | %btn { 2 | background-image: $gradient; 3 | border-radius: 10rem; 4 | border: none; 5 | text-transform: uppercase; 6 | color: #fff; 7 | cursor: pointer; 8 | display: flex; 9 | align-items: center; 10 | transition: all 0.2s; 11 | 12 | &:hover { 13 | transform: scale(1.05); 14 | } 15 | 16 | &:focus { 17 | outline: none; 18 | } 19 | 20 | & > *:first-child { 21 | margin-right: 1rem; 22 | } 23 | } 24 | 25 | .btn { 26 | @extend %btn; 27 | 28 | padding: 1.5rem 4rem; 29 | font-size: 1.5rem; 30 | font-weight: 600; 31 | 32 | svg { 33 | height: 2.25rem; 34 | width: 2.25rem; 35 | fill: currentColor; 36 | } 37 | } 38 | 39 | .btn--small { 40 | &, 41 | &:link, 42 | &:visited { 43 | @extend %btn; 44 | 45 | font-size: 1.4rem; 46 | font-weight: 600; 47 | padding: 1.25rem 2.25rem; 48 | text-decoration: none; 49 | 50 | svg { 51 | height: 1.75rem; 52 | width: 1.75rem; 53 | fill: currentColor; 54 | } 55 | } 56 | } 57 | 58 | .btn--inline { 59 | color: $color-primary; 60 | font-size: 1.3rem; 61 | font-weight: 600; 62 | border: none; 63 | background-color: $color-grey-light-1; 64 | padding: 0.8rem 1.2rem; 65 | border-radius: 10rem; 66 | cursor: pointer; 67 | 68 | display: flex; 69 | align-items: center; 70 | transition: all 0.2s; 71 | 72 | svg { 73 | height: 1.6rem; 74 | width: 1.6rem; 75 | fill: currentColor; 76 | margin: 0 0.2rem; 77 | } 78 | 79 | span { 80 | margin: 0 0.4rem; 81 | } 82 | 83 | &:hover { 84 | color: $color-grad-2; 85 | background-color: $color-grey-light-2; 86 | } 87 | 88 | &:focus { 89 | outline: none; 90 | } 91 | } 92 | 93 | .btn--round { 94 | background-image: $gradient; 95 | border-radius: 50%; 96 | border: none; 97 | cursor: pointer; 98 | height: 4.5rem; 99 | width: 4.5rem; 100 | // margin-left: auto; 101 | transition: all 0.2s; 102 | 103 | display: flex; 104 | align-items: center; 105 | justify-content: center; 106 | 107 | &:hover { 108 | transform: scale(1.07); 109 | } 110 | 111 | &:focus { 112 | outline: none; 113 | } 114 | 115 | svg { 116 | height: 2.5rem; 117 | width: 2.5rem; 118 | fill: #fff; 119 | } 120 | } 121 | 122 | .btn--tiny { 123 | height: 2rem; 124 | width: 2rem; 125 | border: none; 126 | background: none; 127 | cursor: pointer; 128 | 129 | svg { 130 | height: 100%; 131 | width: 100%; 132 | fill: $color-primary; 133 | transition: all 0.3s; 134 | } 135 | 136 | &:focus { 137 | outline: none; 138 | } 139 | 140 | &:hover svg { 141 | fill: $color-grad-2; 142 | transform: translateY(-1px); 143 | } 144 | 145 | &:active svg { 146 | fill: $color-grad-2; 147 | transform: translateY(0); 148 | } 149 | 150 | &:not(:last-child) { 151 | margin-right: 0.3rem; 152 | } 153 | } 154 | 155 | .heading--2 { 156 | font-size: 2rem; 157 | font-weight: 700; 158 | color: $color-primary; 159 | text-transform: uppercase; 160 | margin-bottom: 2.5rem; 161 | text-align: center; 162 | // transform: skewY(-3deg); 163 | } 164 | 165 | .link:link, 166 | .link:visited { 167 | color: $color-grey-dark-2; 168 | } 169 | 170 | .spinner { 171 | margin: 5rem auto; 172 | text-align: center; 173 | 174 | svg { 175 | height: 6rem; 176 | width: 6rem; 177 | fill: $color-primary; 178 | animation: rotate 2s infinite linear; 179 | } 180 | } 181 | 182 | @keyframes rotate { 183 | 0% { 184 | transform: rotate(0); 185 | } 186 | 187 | 100% { 188 | transform: rotate(360deg); 189 | } 190 | } 191 | 192 | .message, 193 | .error { 194 | max-width: 40rem; 195 | margin: 0 auto; 196 | padding: 5rem 4rem; 197 | 198 | display: flex; 199 | 200 | svg { 201 | height: 3rem; 202 | width: 3rem; 203 | fill: $color-primary; 204 | transform: translateY(-0.3rem); 205 | } 206 | 207 | p { 208 | margin-left: 1.5rem; 209 | font-size: 1.8rem; 210 | line-height: 1.5; 211 | font-weight: 600; 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /18-forkify/starter/src/sass/_header.scss: -------------------------------------------------------------------------------- 1 | .header { 2 | grid-area: head; 3 | background-color: $color-grey-light-1; 4 | display: flex; 5 | align-items: center; 6 | justify-content: space-between; 7 | 8 | &__logo { 9 | margin-left: 4rem; 10 | height: 4.6rem; 11 | display: block; 12 | } 13 | } 14 | 15 | .search { 16 | background-color: #fff; 17 | border-radius: 10rem; 18 | display: flex; 19 | align-items: center; 20 | padding-left: 3rem; 21 | transition: all 0.3s; 22 | 23 | &:focus-within { 24 | transform: translateY(-2px); 25 | box-shadow: 0 0.7rem 3rem rgba($color-grey-dark-1, 0.08); 26 | } 27 | 28 | &__field { 29 | border: none; 30 | background: none; 31 | font-family: inherit; 32 | color: inherit; 33 | font-size: 1.7rem; 34 | width: 30rem; 35 | 36 | &:focus { 37 | outline: none; 38 | } 39 | 40 | &::placeholder { 41 | color: $color-grey-light-3; 42 | } 43 | 44 | @media only screen and (max-width: $bp-medium) { 45 | width: auto; 46 | 47 | &::placeholder { 48 | color: white; 49 | } 50 | } 51 | } 52 | 53 | &__btn { 54 | font-weight: 600; 55 | font-family: inherit; 56 | } 57 | } 58 | 59 | .nav { 60 | align-self: stretch; 61 | margin-right: 2.5rem; 62 | 63 | &__list { 64 | list-style: none; 65 | display: flex; 66 | height: 100%; 67 | } 68 | 69 | &__item { 70 | position: relative; 71 | } 72 | 73 | &__btn { 74 | height: 100%; 75 | font-family: inherit; 76 | color: inherit; 77 | font-size: 1.4rem; 78 | font-weight: 700; 79 | text-transform: uppercase; 80 | background: none; 81 | border: none; 82 | cursor: pointer; 83 | padding: 0 1.5rem; 84 | transition: all 0.3s; 85 | 86 | display: flex; 87 | align-items: center; 88 | 89 | svg { 90 | height: 2.4rem; 91 | width: 2.4rem; 92 | fill: $color-primary; 93 | margin-right: 0.7rem; 94 | transform: translateY(-1px); 95 | } 96 | 97 | &:focus { 98 | outline: none; 99 | } 100 | 101 | &:hover { 102 | background-color: $color-grey-light-2; 103 | } 104 | } 105 | } 106 | 107 | .bookmarks { 108 | padding: 1rem 0; 109 | position: absolute; 110 | // right: 0; 111 | right: -2.5rem; 112 | z-index: 10; 113 | width: 40rem; 114 | background-color: #fff; 115 | box-shadow: 0 0.8rem 5rem 2rem rgba($color-grey-dark-1, 0.1); 116 | 117 | visibility: hidden; 118 | opacity: 0; 119 | transition: all 0.5s 0.2s; 120 | 121 | &__list { 122 | list-style: none; 123 | } 124 | 125 | &__field { 126 | cursor: pointer; 127 | padding: 0 4rem; 128 | 129 | display: flex; 130 | align-items: center; 131 | height: 100%; 132 | transition: all 0.3s; 133 | 134 | &:hover { 135 | background-color: $color-grey-light-2; 136 | } 137 | } 138 | 139 | &:hover, 140 | .nav__btn--bookmarks:hover + & { 141 | visibility: visible; 142 | opacity: 1; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /18-forkify/starter/src/sass/_preview.scss: -------------------------------------------------------------------------------- 1 | .preview { 2 | &__link { 3 | &:link, 4 | &:visited { 5 | display: flex; 6 | align-items: center; 7 | padding: 1.5rem 3.25rem; 8 | transition: all 0.3s; 9 | border-right: 1px solid #fff; 10 | text-decoration: none; 11 | } 12 | 13 | &:hover { 14 | background-color: $color-grey-light-1; 15 | transform: translateY(-2px); 16 | } 17 | 18 | &--active { 19 | background-color: $color-grey-light-1; 20 | } 21 | } 22 | 23 | &__fig { 24 | flex: 0 0 5.8rem; 25 | border-radius: 50%; 26 | overflow: hidden; 27 | height: 5.8rem; 28 | margin-right: 2rem; 29 | position: relative; 30 | backface-visibility: hidden; 31 | 32 | &::before { 33 | content: ''; 34 | display: block; 35 | height: 100%; 36 | width: 100%; 37 | position: absolute; 38 | top: 0; 39 | left: 0; 40 | background-image: linear-gradient( 41 | to right bottom, 42 | $color-grad-1, 43 | $color-grad-2 44 | ); 45 | opacity: 0.4; 46 | } 47 | 48 | img { 49 | display: block; 50 | width: 100%; 51 | height: 100%; 52 | object-fit: cover; 53 | transition: all 0.3s; 54 | } 55 | } 56 | 57 | &__data { 58 | display: grid; 59 | width: 100%; 60 | grid-template-columns: 1fr 2rem; 61 | row-gap: 0.1rem; 62 | align-items: center; 63 | } 64 | 65 | &__title { 66 | grid-column: 1/-1; 67 | font-size: 1.45rem; 68 | color: $color-primary; 69 | text-transform: uppercase; 70 | font-weight: 600; 71 | 72 | // This is how text is truncated! 73 | text-overflow: ellipsis; 74 | max-width: 25rem; 75 | white-space: nowrap; 76 | overflow: hidden; 77 | } 78 | 79 | &__publisher { 80 | font-size: 1.15rem; 81 | color: $color-grey-dark-2; 82 | text-transform: uppercase; 83 | font-weight: 600; 84 | } 85 | 86 | &__user-generated { 87 | background-color: darken($color-grey-light-2, 2%); 88 | 89 | display: flex; 90 | align-items: center; 91 | justify-content: center; 92 | height: 2rem; 93 | width: 2rem; 94 | border-radius: 10rem; 95 | 96 | margin-left: auto; 97 | margin-right: 1.75rem; 98 | 99 | svg { 100 | height: 1.2rem; 101 | width: 1.2rem; 102 | fill: $color-primary; 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /18-forkify/starter/src/sass/_recipe.scss: -------------------------------------------------------------------------------- 1 | .recipe { 2 | background-color: $color-grey-light-1; 3 | 4 | /////////// 5 | // FIGURE 6 | &__fig { 7 | height: 32rem; 8 | position: relative; 9 | // transform: scale(1.04) translateY(-1px); 10 | transform-origin: top; 11 | 12 | &::before { 13 | content: ''; 14 | display: block; 15 | height: 100%; 16 | width: 100%; 17 | position: absolute; 18 | top: 0; 19 | left: 0; 20 | background-image: linear-gradient( 21 | to right bottom, 22 | $color-grad-1, 23 | $color-grad-2 24 | ); 25 | opacity: 0.6; 26 | } 27 | } 28 | 29 | &__img { 30 | width: 100%; 31 | display: block; 32 | height: 100%; 33 | object-fit: cover; 34 | } 35 | 36 | &__title { 37 | position: absolute; 38 | bottom: 0; 39 | left: 50%; 40 | transform: translate(-50%, 20%) skewY(-6deg); 41 | color: #fff; 42 | font-weight: 700; 43 | font-size: 3.25rem; 44 | text-transform: uppercase; 45 | width: 50%; 46 | line-height: 1.95; 47 | text-align: center; 48 | 49 | span { 50 | -webkit-box-decoration-break: clone; 51 | box-decoration-break: clone; 52 | padding: 1.3rem 2rem; 53 | background-image: linear-gradient( 54 | to right bottom, 55 | $color-grad-1, 56 | $color-grad-2 57 | ); 58 | } 59 | 60 | @media only screen and (max-width: $bp-medium) { 61 | width: 70%; 62 | } 63 | } 64 | 65 | /////////// 66 | // DETAILS 67 | &__details { 68 | display: flex; 69 | align-items: center; 70 | padding: 7.5rem 8rem 3.5rem 8rem; 71 | } 72 | 73 | &__info { 74 | font-size: 1.65rem; 75 | text-transform: uppercase; 76 | display: flex; 77 | align-items: center; 78 | 79 | &:not(:last-child) { 80 | margin-right: 4.5rem; 81 | } 82 | } 83 | 84 | &__info-icon { 85 | height: 2.35rem; 86 | width: 2.35rem; 87 | fill: $color-primary; 88 | margin-right: 1.15rem; 89 | } 90 | 91 | &__info-data { 92 | margin-right: 0.5rem; 93 | font-weight: 700; 94 | } 95 | 96 | &__info-buttons { 97 | display: flex; 98 | margin-left: 1.6rem; 99 | transform: translateY(-1px); 100 | } 101 | 102 | &__user-generated { 103 | background-color: darken($color-grey-light-2, 2%); 104 | 105 | display: flex; 106 | align-items: center; 107 | justify-content: center; 108 | height: 4rem; 109 | width: 4rem; 110 | border-radius: 10rem; 111 | 112 | margin-left: auto; 113 | margin-right: 1.75rem; 114 | 115 | svg { 116 | height: 2.25rem; 117 | width: 2.25rem; 118 | fill: $color-primary; 119 | } 120 | } 121 | 122 | /////////// 123 | // INGREDIENTS 124 | &__ingredients { 125 | padding: 5rem 8rem; 126 | font-size: 1.6rem; 127 | line-height: 1.4; 128 | background-color: $color-grey-light-2; 129 | display: flex; 130 | flex-direction: column; 131 | align-items: center; 132 | } 133 | 134 | &__ingredient-list { 135 | display: grid; 136 | grid-template-columns: 1fr 1fr; 137 | gap: 2.5rem 3rem; 138 | list-style: none; 139 | } 140 | 141 | &__ingredient { 142 | display: flex; 143 | } 144 | 145 | &__icon { 146 | height: 2rem; 147 | width: 2rem; 148 | fill: $color-primary; 149 | margin-right: 1.1rem; 150 | flex: 0 0 auto; 151 | margin-top: 0.1rem; 152 | } 153 | 154 | &__quantity { 155 | margin-right: 0.5rem; 156 | flex: 0 0 auto; 157 | } 158 | 159 | /////////// 160 | // DIRECTIONS 161 | &__directions { 162 | padding: 5rem 10rem; 163 | padding-bottom: 5rem; 164 | display: flex; 165 | flex-direction: column; 166 | align-items: center; 167 | } 168 | 169 | &__directions-text { 170 | font-size: 1.7rem; 171 | text-align: center; 172 | margin-bottom: 3.5rem; 173 | color: $color-grey-dark-2; 174 | } 175 | 176 | &__publisher { 177 | font-weight: 700; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /18-forkify/starter/src/sass/_searchResults.scss: -------------------------------------------------------------------------------- 1 | .search-results { 2 | padding: 3rem 0; 3 | display: flex; 4 | flex-direction: column; 5 | } 6 | 7 | .results { 8 | list-style: none; 9 | margin-bottom: 2rem; 10 | } 11 | 12 | .pagination { 13 | margin-top: auto; 14 | padding: 0 3.5rem; 15 | 16 | &::after { 17 | content: ''; 18 | display: table; 19 | clear: both; 20 | } 21 | 22 | &__btn { 23 | &--prev { 24 | float: left; 25 | } 26 | &--next { 27 | float: right; 28 | } 29 | } 30 | } 31 | 32 | .copyright { 33 | color: $color-grey-dark-2; 34 | font-size: 1.2rem; 35 | padding: 0 3.5rem; 36 | margin-top: 4rem; 37 | 38 | .twitter-link:link, 39 | .twitter-link:visited { 40 | color: $color-grey-dark-2; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /18-forkify/starter/src/sass/_upload.scss: -------------------------------------------------------------------------------- 1 | .add-recipe-window { 2 | position: fixed; 3 | top: 50%; 4 | left: 50%; 5 | transform: translate(-50%, -50%); 6 | width: 100rem; 7 | background-color: white; 8 | border-radius: 9px; 9 | 10 | padding: 5rem 6rem; 11 | box-shadow: 0 4rem 6rem rgba(0, 0, 0, 0.25); 12 | z-index: 1000; 13 | transition: all 0.5s; 14 | 15 | .btn--close-modal { 16 | font-family: inherit; 17 | color: inherit; 18 | position: absolute; 19 | top: 0.5rem; 20 | right: 1.6rem; 21 | font-size: 3.5rem; 22 | cursor: pointer; 23 | border: none; 24 | background: none; 25 | } 26 | } 27 | 28 | .overlay { 29 | position: fixed; 30 | top: 0; 31 | left: 0; 32 | width: 100%; 33 | height: 100%; 34 | background-color: rgba(0, 0, 0, 0.4); 35 | backdrop-filter: blur(4px); 36 | z-index: 100; 37 | transition: all 0.5s; 38 | } 39 | 40 | .hidden { 41 | visibility: hidden; 42 | opacity: 0; 43 | } 44 | 45 | .upload { 46 | display: grid; 47 | grid-template-columns: 1fr 1fr; 48 | gap: 4rem 6rem; 49 | 50 | &__column { 51 | display: grid; 52 | grid-template-columns: 1fr 2.8fr; 53 | align-items: center; 54 | gap: 1.5rem; 55 | 56 | & label { 57 | font-size: 1.5rem; 58 | font-weight: 600; 59 | color: inherit; 60 | } 61 | 62 | & input { 63 | font-size: 1.5rem; 64 | padding: 0.8rem 1rem; 65 | border: 1px solid #ddd; 66 | border-radius: 0.5rem; 67 | transition: all 0.2s; 68 | 69 | &::placeholder { 70 | color: $color-grey-light-3; 71 | } 72 | 73 | &:focus { 74 | outline: none; 75 | border: 1px solid $color-primary; 76 | background-color: $color-grey-light-1; 77 | } 78 | } 79 | 80 | & button { 81 | grid-column: 1 / span 2; 82 | justify-self: center; 83 | margin-top: 1rem; 84 | } 85 | } 86 | 87 | &__heading { 88 | font-size: 2.25rem; 89 | font-weight: 700; 90 | text-transform: uppercase; 91 | margin-bottom: 1rem; 92 | grid-column: 1/-1; 93 | } 94 | 95 | &__btn { 96 | grid-column: 1 / -1; 97 | justify-self: center; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /18-forkify/starter/src/sass/main.scss: -------------------------------------------------------------------------------- 1 | @import 'base'; 2 | @import 'components'; 3 | @import 'header'; 4 | @import 'preview'; 5 | @import 'searchResults'; 6 | @import 'recipe'; 7 | @import 'upload'; 8 | --------------------------------------------------------------------------------