├── 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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/07-Pig-Game/final/dice-1.png -------------------------------------------------------------------------------- /07-Pig-Game/final/dice-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/07-Pig-Game/final/dice-2.png -------------------------------------------------------------------------------- /07-Pig-Game/final/dice-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/07-Pig-Game/final/dice-3.png -------------------------------------------------------------------------------- /07-Pig-Game/final/dice-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/07-Pig-Game/final/dice-4.png -------------------------------------------------------------------------------- /07-Pig-Game/final/dice-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/07-Pig-Game/final/dice-5.png -------------------------------------------------------------------------------- /07-Pig-Game/final/dice-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/07-Pig-Game/starter/dice-1.png -------------------------------------------------------------------------------- /07-Pig-Game/starter/dice-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/07-Pig-Game/starter/dice-2.png -------------------------------------------------------------------------------- /07-Pig-Game/starter/dice-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/07-Pig-Game/starter/dice-3.png -------------------------------------------------------------------------------- /07-Pig-Game/starter/dice-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/07-Pig-Game/starter/dice-4.png -------------------------------------------------------------------------------- /07-Pig-Game/starter/dice-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/07-Pig-Game/starter/dice-5.png -------------------------------------------------------------------------------- /07-Pig-Game/starter/dice-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/11-Arrays-Bankist/final/Bankist-flowchart.png -------------------------------------------------------------------------------- /11-Arrays-Bankist/final/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/11-Arrays-Bankist/starter/Bankist-flowchart.png -------------------------------------------------------------------------------- /11-Arrays-Bankist/starter/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/12-Numbers-Dates-Timers-Bankist/final/Bankist-flowchart.png -------------------------------------------------------------------------------- /12-Numbers-Dates-Timers-Bankist/final/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/12-Numbers-Dates-Timers-Bankist/starter/Bankist-flowchart.png -------------------------------------------------------------------------------- /12-Numbers-Dates-Timers-Bankist/starter/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/final/img/card-lazy.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/card.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/final/img/card.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/digital-lazy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/final/img/digital-lazy.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/digital.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/final/img/digital.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/grow-lazy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/final/img/grow-lazy.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/grow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/final/img/grow.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/final/img/hero.png -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/final/img/icon.png -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/img-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/final/img/img-1.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/img-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/final/img/img-2.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/img-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/final/img/img-3.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/img-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/final/img/img-4.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/final/img/logo.png -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/user-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/final/img/user-1.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/user-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/final/img/user-2.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/user-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/starter/img/card-lazy.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/card.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/starter/img/card.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/digital-lazy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/starter/img/digital-lazy.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/digital.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/starter/img/digital.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/grow-lazy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/starter/img/grow-lazy.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/grow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/starter/img/grow.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/starter/img/hero.png -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/starter/img/icon.png -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/img-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/starter/img/img-1.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/img-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/starter/img/img-2.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/img-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/starter/img/img-3.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/img-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/starter/img/img-4.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/starter/img/logo.png -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/user-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/starter/img/user-1.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/user-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/13-Advanced-DOM-Bankist/starter/img/user-2.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/user-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/15-Mapty/final/Mapty-architecture-final.png -------------------------------------------------------------------------------- /15-Mapty/final/Mapty-architecture-part-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/15-Mapty/final/Mapty-architecture-part-1.png -------------------------------------------------------------------------------- /15-Mapty/final/Mapty-flowchart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/15-Mapty/final/Mapty-flowchart.png -------------------------------------------------------------------------------- /15-Mapty/final/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/15-Mapty/final/icon.png -------------------------------------------------------------------------------- /15-Mapty/final/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/15-Mapty/starter/Mapty-architecture-final.png -------------------------------------------------------------------------------- /15-Mapty/starter/Mapty-architecture-part-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/15-Mapty/starter/Mapty-architecture-part-1.png -------------------------------------------------------------------------------- /15-Mapty/starter/Mapty-flowchart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/15-Mapty/starter/Mapty-flowchart.png -------------------------------------------------------------------------------- /15-Mapty/starter/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/16-Asynchronous/final/img/img-1.jpg -------------------------------------------------------------------------------- /16-Asynchronous/final/img/img-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/16-Asynchronous/final/img/img-2.jpg -------------------------------------------------------------------------------- /16-Asynchronous/final/img/img-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/16-Asynchronous/starter/img/img-1.jpg -------------------------------------------------------------------------------- /16-Asynchronous/starter/img/img-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/16-Asynchronous/starter/img/img-2.jpg -------------------------------------------------------------------------------- /16-Asynchronous/starter/img/img-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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 | // The Module Pattern 29 | 30 | const ShoppingCart2 = (function () { 31 | const cart = []; 32 | const shippingCost = 10; 33 | const totalPrice = 237; 34 | const totalQuantity = 23; 35 | 36 | const addToCart = function (product, quantity) { 37 | cart.push({ product, quantity }); 38 | console.log( 39 | `${quantity} ${product} added to cart (sipping cost is ${shippingCost})` 40 | ); 41 | }; 42 | 43 | const orderStock = function (product, quantity) { 44 | console.log(`${quantity} ${product} ordered from supplier`); 45 | }; 46 | 47 | return { 48 | addToCart, 49 | cart, 50 | totalPrice, 51 | totalQuantity, 52 | }; 53 | })(); 54 | 55 | ShoppingCart2.addToCart('apple', 4); 56 | ShoppingCart2.addToCart('pizza', 2); 57 | console.log(ShoppingCart2); 58 | console.log(ShoppingCart2.shippingCost); 59 | 60 | 61 | /////////////////////////////////////// 62 | // CommonJS Modules 63 | // Export 64 | export.addTocart = function (product, quantity) { 65 | cart.push({ product, quantity }); 66 | console.log( 67 | `${quantity} ${product} added to cart (sipping cost is ${shippingCost})` 68 | ); 69 | }; 70 | 71 | // Import 72 | const { addTocart } = require('./shoppingCart.js'); 73 | */ 74 | 75 | /////////////////////////////////////// 76 | // Introduction to NPM 77 | // import cloneDeep from './node_modules/lodash-es/cloneDeep.js'; 78 | import cloneDeep from 'lodash-es'; 79 | 80 | const state = { 81 | cart: [ 82 | { product: 'bread', quantity: 5 }, 83 | { product: 'pizza', quantity: 5 }, 84 | ], 85 | user: { loggedIn: true }, 86 | }; 87 | const stateClone = Object.assign({}, state); 88 | const stateDeepClone = cloneDeep(state); 89 | 90 | state.user.loggedIn = false; 91 | console.log(stateClone); 92 | 93 | console.log(stateDeepClone); 94 | 95 | if (module.hot) { 96 | module.hot.accept(); 97 | } 98 | 99 | class Person { 100 | #greeting = 'Hey'; 101 | constructor(name) { 102 | this.name = name; 103 | console.log(`${this.#greeting}, ${this.name}`); 104 | } 105 | } 106 | const jonas = new Person('Jonas'); 107 | 108 | console.log('Jonas' ?? null); 109 | 110 | console.log(cart.find(el => el.quantity >= 2)); 111 | Promise.resolve('TEST').then(x => console.log(x)); 112 | 113 | import 'core-js/stable'; 114 | // import 'core-js/stable/array/find'; 115 | // import 'core-js/stable/promise'; 116 | 117 | // Polifilling async functions 118 | import 'regenerator-runtime/runtime'; 119 | -------------------------------------------------------------------------------- /17-Modern-JS-Modules-Tooling/final/shoppingCart.js: -------------------------------------------------------------------------------- 1 | // Exporting module 2 | console.log('Exporting module'); 3 | 4 | const shippingCost = 10; 5 | export const cart = []; 6 | 7 | export const addToCart = function (product, quantity) { 8 | cart.push({ product, quantity }); 9 | console.log(`${quantity} ${product} added to cart`); 10 | }; 11 | 12 | const totalPrice = 237; 13 | const totalQuantity = 23; 14 | 15 | export { totalPrice, totalQuantity as tq }; 16 | 17 | export default function (product, quantity) { 18 | cart.push({ product, quantity }); 19 | console.log(`${quantity} ${product} added to cart`); 20 | } 21 | -------------------------------------------------------------------------------- /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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/18-forkify/final/src/img/favicon.png -------------------------------------------------------------------------------- /18-forkify/final/src/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/18-forkify/starter/forkify-architecture-recipe-loading.png -------------------------------------------------------------------------------- /18-forkify/starter/forkify-flowchart-part-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/18-forkify/starter/forkify-flowchart-part-1.png -------------------------------------------------------------------------------- /18-forkify/starter/forkify-flowchart-part-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/18-forkify/starter/forkify-flowchart-part-2.png -------------------------------------------------------------------------------- /18-forkify/starter/forkify-flowchart-part-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/18-forkify/starter/forkify-flowchart-part-3.png -------------------------------------------------------------------------------- /18-forkify/starter/src/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/18-forkify/starter/src/img/favicon.png -------------------------------------------------------------------------------- /18-forkify/starter/src/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nirzaf/complete-javascript-course/0a217ff24696034937dcc0a7a19f57c4735bc289/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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Course Material and FAQ for my Complete JavaScript Course 2 | 3 | This repo contains starter files and final code for all sections and projects contained in the course. 4 | 5 | Use starter code to start each section, and **final code to compare it with your own code whenever something doesn't work**! 6 | 7 | 👇 **_Please read the following Frequently Asked Questions (FAQ) carefully before starting the course_** 👇 8 | 9 | ## FAQ 10 | 11 | ### Q1: How do I download the files? 12 | 13 | **A:** If you're new to GitHub and just want to download the entire code, hit the green button saying "Code", and then choose the "Download ZIP" option. If you can't see the button (on mobile), use [this link](https://github.com/jonasschmedtmann/complete-javascript-course/archive/master.zip) instead. 14 | 15 | ### Q2: I'm looking for the old course version (v1) files. Where can I find them? 16 | 17 | **A:** They are in this same repo, but in the [v1 branch](https://github.com/jonasschmedtmann/complete-javascript-course/tree/v1). So just go to [v1](https://github.com/jonasschmedtmann/complete-javascript-course/tree/v1), and download the code from there. 18 | 19 | ### Q3: I'm stuck! Where do I get help? 20 | 21 | **A:** Have you actually tried to fix the problem on your own? Have you compared your code to the final code? If you failed fixing your problem, please **post a detailed description of the problem to the Q&A area of that video over at Udemy**, along with a [codepen](https://codepen.io/pen/) containing your code. You will get help there. Please don't send me a personal message or email to fix coding problems. 22 | 23 | ### Q4: What VSCode theme are you using? 24 | 25 | **A:** I use Monokai Pro for all my coding and course production. It's a paid theme (I', **not** affiliated with them), but you can actually use the free demo version forever 😅 26 | 27 | ### Q5: Can I see a final version of the course projects? 28 | 29 | **A:** Sure! Here you go: 30 | 31 | - [Pig Game](https://pig-game-v2.netlify.app) (DOM Manipulation) 32 | - [Bankist](https://bankist.netlify.app/) (Arrays, Numbers, Dates, Timers. Fake "log in" with user `js` and PIN `1111`) 33 | - [Bankist Site](https://bankist-dom.netlify.app/) (Advanced DOM and Events) 34 | - [Mapty](https://mapty.netlify.app/) (OOP, Geolocation, Project planning) 35 | - [forkify](https://forkify-v2.netlify.app/) (Final advanced project) 36 | 37 | ### Q6: Videos don't load, can you fix it? 38 | 39 | **A:** Unfortunately, there is nothing I can do about it. The course is hosted on Udemy, and sometimes they have technical issues like this. Please just come back a bit later or [contact their support team](https://support.udemy.com/hc/en-us). 40 | 41 | ### Q7: Videos are blurred / have low quality, can you fix it? 42 | 43 | **A:** Please open video settings and change the quality from 'Auto' to another value, for example 720p. If that doesn't help, please [contact the Udemy support team](https://support.udemy.com/hc/en-us). 44 | 45 | ### Q8: Are the videos downloadable? 46 | 47 | **A:** Yes! I made all videos downloadable from Udemy so you can learn even without an internet connection. To download a video, use the settings icon in the right bottom corner of the video player. Videos have to be downloaded individually. 48 | 49 | ### Q9: I want to put these projects in my portfolio. Is that allowed? 50 | 51 | **A:** Absolutely! Just make sure you actually built them yourself by following the course, and that you understand what you did. What is **not allowed** is that you create your own course/videos/articles based on this course's content! 52 | 53 | ### Q10: You mentioned your resources page. Where can I find it? 54 | 55 | **A:** It's on my website at . You can subscribe for updates 😉 56 | 57 | ### Q11: I love your courses and want to get updates on new courses. How? 58 | 59 | **A:** First, you can subscribe to my email list [at my website](http://codingheroes.io/resources). Plus, I make important announcements on twitter [@jonasschmedtman](https://twitter.com/jonasschmedtman), so you should definitely follow me there 🔥 60 | 61 | ### Q12: How do I get my certificate of completion? 62 | 63 | **A:** A certificate of completion is provided by Udemy after you complete 100% of the course. After completing the course, just click on the "Your progress" indicator in the top right-hand corner of the course page. If you want to change your name on the certificate, please [contact the Udemy support team](https://support.udemy.com/hc/en-us). 64 | 65 | ### Q13: Can you add subtitles in my language? 66 | 67 | **A:** No. I provide professional English captions, but Udemy is responsible for subtitles in all other languages (automatic translations). So please [contact the Udemy support team](https://support.udemy.com/hc/en-us) to request your own language. 68 | 69 | ### Q14: Do you accept pull requests? 70 | 71 | **A:** No, for the simple reason that I want this repository to contain the _exact_ same code that is shown in the videos. However, please feel free to add an issue if you found one. 72 | --------------------------------------------------------------------------------