├── .DS_Store ├── .vscode └── settings.json ├── 01-Fundamentals-Part-1 ├── assignments.js ├── final │ ├── index.html │ └── script.js ├── index.html └── script.js ├── 02-Fundamentals-Part-2 ├── assignments.js ├── final │ ├── index.html │ └── script.js ├── index.html ├── script.js └── starter │ ├── index.html │ └── script.js ├── 03-Developer-Skills ├── final │ ├── .prettierrc │ ├── index.html │ └── script.js ├── 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 ├── index.html ├── script.js ├── starter │ ├── .prettierrc │ ├── index.html │ ├── script.js │ └── style.css └── style.css ├── 06-Modal ├── final │ ├── .prettierrc │ ├── index.html │ ├── script.js │ └── style.css ├── index.html ├── script.js ├── starter │ ├── .prettierrc │ ├── index.html │ ├── script.js │ └── style.css └── style.css ├── 07-Pig-Game ├── dice-1.png ├── dice-2.png ├── dice-3.png ├── dice-4.png ├── dice-5.png ├── dice-6.png ├── 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 ├── index.html ├── pig-game-flowchart.png ├── script.js ├── 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 └── style.css ├── 08-Behind-the-Scenes ├── final │ ├── .prettierrc │ ├── index.html │ └── script.js └── starter │ ├── .prettierrc │ ├── index.html │ └── script.js ├── 09-Data-Structures-Operators ├── .DS_Store ├── assignments.js ├── final │ ├── .prettierrc │ ├── index.html │ └── script.js └── starter │ ├── .prettierrc │ ├── coding-challenge-2.js │ ├── coding-chellenge-1.js │ ├── 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 └── course-material-v2.0 ├── all-coding-challenges.pdf ├── assignments-js-fundamentals.pdf └── theory-lectures-v2.pdf /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/.DS_Store -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /01-Fundamentals-Part-1/assignments.js: -------------------------------------------------------------------------------- 1 | //////////////////////////////// 2 | // LECTURE: Values and Variables 3 | 4 | // 1.Declare variables called 'country', 'continent 'and 'population' and assign their values according to your own country(population in millions) 5 | let country = 'Uruguay'; 6 | let continent = 'South America'; 7 | let population = 3.4; 8 | 9 | // 2.Log their values to the console 10 | console.log(country); 11 | console.log(continent); 12 | console.log(population); 13 | 14 | ////////////////////// 15 | // LECTURE: Data Types 16 | 17 | // 1.Declare a variable called 'isIsland' and set its value according to your country. The variable should hold a Booleanvalue. Also declare a variable 'language', but don't assign it any value yet 18 | let isIsland = false; 19 | let language; 20 | 21 | // 2.Log the types of 'isIsland', 'population', 'country' and 'language' to the console 22 | console.log(typeof Boolean); // function 23 | console.log(typeof population); // number 24 | console.log(typeof country); // string 25 | console.log(typeof language); // undefined 26 | 27 | ////////////////////////////// 28 | // LECTURE: let, const and var 29 | 30 | // 1.Set the value of 'language' to the language spoken where you live (some countries have multiple languages, but just choose one) 31 | language = 'spanish'; 32 | 33 | // 2.Think about which variables should be const variables (which values will never change, and which might change?). Then, change these variables to const. 34 | const country2 = 'Uruguay'; 35 | const continent2 = 'South America'; 36 | const isIsland2 = false; 37 | 38 | // 3.Try to change one of the changed variables now, and observe what happens 39 | // isIsland2 = true; // TypeError: Assignment to constant variable. 40 | 41 | /////////////////////////// 42 | // LECTURE: Basic Operators 43 | 44 | // 1.If your country split in half, and each half would contain half the population, then how many people would live in each half? 45 | console.log(population / 2); 46 | 47 | // 2.Increase the populationof your country by 1 and log the result to the console 48 | population++; 49 | console.log(population); 50 | 51 | // 3.Finland has a population of 6 million. Does your country have more people than Finland? 52 | console.log(population < 6); 53 | 54 | // 4.The average population of a country is 33 million people. Does your country have less people than the average country? 55 | console.log(population < 33); 56 | 57 | // 5.Based on the variables you created, create a new variable 'description 'which contains a string with this format: 'Portugal is in Europe, and its 11 million people speak portuguese' 58 | const description1 = country + ' is in ' + continent + ', and its ' + population + ' million people speak ' + language; 59 | 60 | console.log(description1); 61 | 62 | ///////////////////////////////////////// 63 | // LECTURE: Strings and Template Literals 64 | 65 | // 1.Recreate the 'description' variable from the last assignment, this time using the template literal syntax 66 | const description2 = `${country} is in ${continent}, and its ${population} million people speak ${language}`; 67 | 68 | console.log(description2); 69 | 70 | ////////////////////////////////////////////////// 71 | // LECTURE: Taking Decisions: if / else Statements 72 | 73 | // 1.If your country's population is greater that 33 million, log a string like this to the console: 'Portugal's population is above average'. Otherwise, log a string like 'Portugal's population is 22 million below average' (the 22 is the average of 33 minus the country's population) 74 | if (country > 33) { 75 | console.log(`${country}'s population is above average`); 76 | } else { 77 | console.log(`${country}'s population is ${33 - population} million below average`); 78 | } 79 | 80 | // 2.After checking the result, change the population temporarily to 13 and then to 130. See the different results, and set the population back to original 81 | 82 | //////////////////////////////////////// 83 | // LECTURE: Type Conversion and Coercion 84 | 85 | // 1.Predict the result of these 5 operations without executing them:'9' -'5';'19' -'13' + '17';'19' -'13' + 17;'123' < 57;5 + 6 + '4' + 9 -4 -2; 86 | 87 | // 2.Execute the operations to check if you were right 88 | -------------------------------------------------------------------------------- /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/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/assignments.js: -------------------------------------------------------------------------------- 1 | //////////////////////////////// 2 | // LECTURE: 3 | 4 | // 1. 5 | -------------------------------------------------------------------------------- /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/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/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/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/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/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 | 25 | const temperatures = [3, -2, -6, -1, 'error', 9, 13, 17, 15, 14, 9, 5]; 26 | 27 | const calcTempAmplitude = function (temps) { 28 | let min = temps[0]; 29 | let max = temps[0]; 30 | 31 | for (let i = 0; i < temps.length; i++) { 32 | if (typeof temps[1] !== 'number') continue; 33 | if (temps[i] > max) max = temps[i]; 34 | if (temps[i] < min) min = temps[i]; 35 | } 36 | console.log(max, min); 37 | return max - min; 38 | }; 39 | 40 | console.log(calcTempAmplitude([3, 7, 4, 1])); 41 | // calcTempAmplitude(temperatures); 42 | 43 | // PROBLEM 2: 44 | // Function should now receive 2 arrays of temps 45 | 46 | // 1) Understanding the problem 47 | // - With 2 arrays, should we implement functionality twice? NO! Just merge two arrays 48 | 49 | // 2) Breaking up into sub-problems 50 | // - Merge 2 arrays 51 | 52 | const calcTempAmplitudeNew = function (t1, t2) { 53 | const temps = t1.concat(t2); 54 | 55 | let max = temps[0]; 56 | let min = temps[0]; 57 | 58 | for (let i = 0; i < temps.length; i++) { 59 | const curTemp = temps[i]; 60 | 61 | if (typeof curTemp !== 'number') continue; 62 | if (curTemp > max) max = curTemp; 63 | if (curTemp < min) min = curTemp; 64 | } 65 | console.log(max, min); 66 | return max - min; 67 | }; 68 | const amplitudeNew = calcTempAmplitudeNew([3, 5, 1], [9, 0, 5]); 69 | console.log(amplitudeNew); 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 | // Coding Challenge #1 120 | 121 | /* 122 | Given an array of forecasted maximum temperatures, the thermometer displays a string with these temperatures. 123 | 124 | Example: [17, 21, 23] will print "... 17ºC in 1 days ... 21ºC in 2 days ... 23ºC in 3 days ..." 125 | 126 | Create a function 'printForecast' which takes in an array 'arr' and logs a string like the above to the console. 127 | 128 | Use the problem-solving framework: Understand the problem and break it up into sub-problems! 129 | 130 | TEST DATA 1: [17, 21, 23] 131 | TEST DATA 2: [12, 5, -5, 0, 4] 132 | */ 133 | 134 | function printForecast(arr) { 135 | let str = ''; 136 | 137 | for (let i = 0; i < arr.length; i++) { 138 | str += ` ... ${arr[i]}ºC in ${i + 1} days`; 139 | } 140 | return `${str} ...`; 141 | } 142 | 143 | console.log(printForecast([17, 21, 23])); 144 | console.log(printForecast([12, 5, -5, 0, 4])); 145 | -------------------------------------------------------------------------------- /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/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/script.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | let secretNumber = Math.trunc(Math.random() * 20) + 1; 4 | let score = 20; 5 | let highscore = 0; 6 | 7 | // document.querySelector('.check').addEventListener('click', function () { 8 | // const guess = Number(document.querySelector('.guess').value); 9 | // console.log(secretNumber, guess, typeof guess); 10 | 11 | // if (!guess) { 12 | // document.querySelector('.message').textContent = '⛔️ No number!'; 13 | // } else if (guess === secretNumber) { 14 | // document.querySelector('.message').textContent = '🎉 Correct Number!'; 15 | // document.querySelector('.number').textContent = secretNumber; 16 | 17 | // document.querySelector('body').style.backgroundColor = '#60b347'; 18 | // document.querySelector('.number').style.width = '30rem'; 19 | 20 | // if (score > highscore) { 21 | // highscore = score; 22 | // document.querySelector('.highscore').textContent = highscore; 23 | // } 24 | // } else if (guess > secretNumber) { 25 | // if (score > 1) { 26 | // document.querySelector('.message').textContent = '📈 Too high!'; 27 | // score--; 28 | // document.querySelector('.score').textContent = score; 29 | // } else { 30 | // document.querySelector('.message').textContent = '💥 You lost the game!'; 31 | // document.querySelector('.score').textContent = 0; 32 | // } 33 | // } else if (guess < secretNumber) { 34 | // if (score > 1) { 35 | // document.querySelector('.message').textContent = '📉 Too low!'; 36 | // score--; 37 | // document.querySelector('.score').textContent = score; 38 | // } else { 39 | // document.querySelector('.message').textContent = '💥 You lost the game!'; 40 | // document.querySelector('.score').textContent = 0; 41 | // } 42 | // } 43 | // }); 44 | 45 | /////////////////////////////////////// 46 | // Coding Challenge #1 47 | 48 | /* 49 | Implement a game rest functionality, so that the player can make a new guess! Here is how: 50 | 51 | 1. Select the element with the 'again' class and attach a click event handler 52 | 2. In the handler function, restore initial values of the score and secretNumber variables 53 | 3. Restore the initial conditions of the message, number, score and guess input field 54 | 4. Also restore the original background color (#222) and number width (15rem) 55 | 56 | GOOD LUCK 😀 57 | */ 58 | 59 | document.querySelector('.again').addEventListener('click', function () { 60 | secretNumber = Math.trunc(Math.random() * 20) + 1; 61 | console.log(secretNumber); 62 | 63 | score = 20; 64 | document.querySelector('.score').textContent = score; 65 | document.querySelector('.guess').value = ''; 66 | document.querySelector('.message').textContent = 'Start guessing...'; 67 | document.querySelector('.number').textContent = '?'; 68 | document.querySelector('.number').style.width = '15rem'; 69 | document.querySelector('body').style.backgroundColor = '#222'; 70 | }); 71 | 72 | ////////////////////////////////// 73 | // refactor 74 | 75 | document.querySelector('.check').addEventListener('click', function () { 76 | const guess = Number(document.querySelector('.guess').value); 77 | console.log(secretNumber, guess, typeof guess); 78 | 79 | if (!guess) { 80 | document.querySelector('.message').textContent = '⛔️ No number!'; 81 | } else if (guess === secretNumber) { 82 | document.querySelector('.message').textContent = '🎉 Correct Number!'; 83 | document.querySelector('.number').textContent = secretNumber; 84 | 85 | document.querySelector('body').style.backgroundColor = '#60b347'; 86 | document.querySelector('.number').style.width = '30rem'; 87 | 88 | if (score > highscore) { 89 | highscore = score; 90 | document.querySelector('.highscore').textContent = highscore; 91 | } 92 | } else if (guess > secretNumber) { 93 | if (guess !== secretNumber) { 94 | document.querySelector('.message').textContent = 95 | guess > secretNumber ? '📈 Too high!' : '📉 Too low!'; 96 | score--; 97 | document.querySelector('.score').textContent = score; 98 | } else { 99 | document.querySelector('.message').textContent = '💥 You lost the game!'; 100 | document.querySelector('.score').textContent = 0; 101 | } 102 | } 103 | }); 104 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /05-Guess-My-Number/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/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/script.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const btnsShowModal = document.querySelectorAll('.show-modal'); 4 | const btnCloseModal = document.querySelector('.close-modal'); 5 | const modal = document.querySelector('.modal'); 6 | const overlay = document.querySelector('.overlay'); 7 | 8 | const showModal = 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 < btnsShowModal.length; i++) 19 | btnsShowModal[i].addEventListener('click', showModal); 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/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 | -------------------------------------------------------------------------------- /06-Modal/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/dice-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/07-Pig-Game/dice-1.png -------------------------------------------------------------------------------- /07-Pig-Game/dice-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/07-Pig-Game/dice-2.png -------------------------------------------------------------------------------- /07-Pig-Game/dice-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/07-Pig-Game/dice-3.png -------------------------------------------------------------------------------- /07-Pig-Game/dice-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/07-Pig-Game/dice-4.png -------------------------------------------------------------------------------- /07-Pig-Game/dice-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/07-Pig-Game/dice-5.png -------------------------------------------------------------------------------- /07-Pig-Game/dice-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/07-Pig-Game/dice-6.png -------------------------------------------------------------------------------- /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/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/07-Pig-Game/final/dice-1.png -------------------------------------------------------------------------------- /07-Pig-Game/final/dice-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/07-Pig-Game/final/dice-2.png -------------------------------------------------------------------------------- /07-Pig-Game/final/dice-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/07-Pig-Game/final/dice-3.png -------------------------------------------------------------------------------- /07-Pig-Game/final/dice-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/07-Pig-Game/final/dice-4.png -------------------------------------------------------------------------------- /07-Pig-Game/final/dice-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/07-Pig-Game/final/dice-5.png -------------------------------------------------------------------------------- /07-Pig-Game/final/dice-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/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/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/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/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/pig-game-flowchart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/07-Pig-Game/pig-game-flowchart.png -------------------------------------------------------------------------------- /07-Pig-Game/script.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const score0El = document.querySelector('#score--0'); 4 | const score1El = document.getElementById('score--1'); 5 | const diceEl = document.querySelector('.dice'); 6 | // buttons 7 | const btnNew = document.querySelector('.btn--new'); 8 | const btnRoll = document.querySelector('.btn--roll'); 9 | const btnHold = document.querySelector('.btn--hold'); 10 | 11 | // starting conditions 12 | score0El.textContent = 0; 13 | score1El.textContent = 0; 14 | diceEl.classList.add('hidden'); 15 | 16 | // rolling dice functionality 17 | btnRoll.addEventListener('click', function() { 18 | // 1. generating a random dice roll 19 | let diceNum = Math.trunc((Math.random() * 6) + 1); 20 | console.log(diceNum); 21 | // 2. display dice 22 | diceEl.classList.remove('hidden'); 23 | diceEl.src=`dice-${diceNum}.png`; 24 | // 3. checked for rolled 1: if true, switch to next player 25 | }); 26 | -------------------------------------------------------------------------------- /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/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/07-Pig-Game/starter/dice-1.png -------------------------------------------------------------------------------- /07-Pig-Game/starter/dice-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/07-Pig-Game/starter/dice-2.png -------------------------------------------------------------------------------- /07-Pig-Game/starter/dice-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/07-Pig-Game/starter/dice-3.png -------------------------------------------------------------------------------- /07-Pig-Game/starter/dice-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/07-Pig-Game/starter/dice-4.png -------------------------------------------------------------------------------- /07-Pig-Game/starter/dice-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/07-Pig-Game/starter/dice-5.png -------------------------------------------------------------------------------- /07-Pig-Game/starter/dice-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/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/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/07-Pig-Game/starter/pig-game-flowchart.png -------------------------------------------------------------------------------- /07-Pig-Game/starter/script.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/07-Pig-Game/starter/script.js -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /07-Pig-Game/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 | -------------------------------------------------------------------------------- /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/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/09-Data-Structures-Operators/.DS_Store -------------------------------------------------------------------------------- /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/coding-challenge-2.js: -------------------------------------------------------------------------------- 1 | // Coding Challenge #2 2 | 3 | /* 4 | Let's continue with our football betting app! 5 | 6 | 1. Loop over the game.scored array and print each player name to the console, along with the goal number (Example: "Goal 1: Lewandowski") 7 | 2. Use a loop to calculate the average odd and log it to the console (We already studied how to calculate averages, you can go check if you don't remember) 8 | 3. Print the 3 odds to the console, but in a nice formatted way, exaclty like this: 9 | Odd of victory Bayern Munich: 1.33 10 | Odd of draw: 3.25 11 | Odd of victory Borrussia Dortmund: 6.5 12 | Get the team names directly from the game object, don't hardcode them (except for "draw"). HINT: Note how the odds and the game objects have the same property names 😉 13 | 14 | BONUS: Create an object called 'scorers' which contains the names of the players who scored as properties, and the number of goals as the value. In this game, it will look like this: 15 | { 16 | Gnarby: 1, 17 | Hummels: 1, 18 | Lewandowski: 2 19 | } 20 | 21 | GOOD LUCK 😀 22 | */ 23 | 24 | const game = { 25 | team1: 'Bayern Munich', 26 | team2: 'Borrussia Dortmund', 27 | players: [ 28 | [ 29 | 'Neuer', 30 | 'Pavard', 31 | 'Martinez', 32 | 'Alaba', 33 | 'Davies', 34 | 'Kimmich', 35 | 'Goretzka', 36 | 'Coman', 37 | 'Muller', 38 | 'Gnarby', 39 | 'Lewandowski', 40 | ], 41 | [ 42 | 'Burki', 43 | 'Schulz', 44 | 'Hummels', 45 | 'Akanji', 46 | 'Hakimi', 47 | 'Weigl', 48 | 'Witsel', 49 | 'Hazard', 50 | 'Brandt', 51 | 'Sancho', 52 | 'Gotze', 53 | ], 54 | ], 55 | score: '4:0', 56 | scored: ['Lewandowski', 'Gnarby', 'Lewandowski', 'Hummels'], 57 | date: 'Nov 9th, 2037', 58 | odds: { 59 | team1: 1.33, 60 | x: 3.25, 61 | team2: 6.5, 62 | }, 63 | }; 64 | 65 | // 1. 66 | // for (const [item, name] of game.scored.entries()) { 67 | // console.log(`Goal ${item}: ${name}`) 68 | // } 69 | 70 | // 2. 71 | // const odds = Object.values(game.odds) 72 | // const avgOdd = odds.reduce((a, b) => (a + b) / odds.length) 73 | // console.log(avgOdd) 74 | 75 | // let average = 0 76 | // const odds = Object.values(game.odds) 77 | 78 | // for (const odd of odds) { 79 | // average += odd 80 | // } 81 | // average /= odds.length 82 | 83 | // 3. 84 | // const obj = Object.entries(game.odds) 85 | 86 | // for (const [key, value] of obj) { 87 | // const teamStr = key === 'x' ? 'draw' : `victory ${game[key]}` 88 | 89 | // console.log(`Odd of ${teamStr}: ${value}`) 90 | // // console.log(game[key] !== undefined ? `Odd of victory ${game[key]}: ${value}` : `Odd of draw: ${value}`) 91 | // } 92 | 93 | // bonus 94 | // const scorers = {} 95 | // const goals = [1, 1, 2] 96 | 97 | // for (const player of game.scored) { 98 | // scorers[player] ? scorers[player]++ : (scorers[player] = 1) 99 | // } 100 | // console.log(scorers) 101 | -------------------------------------------------------------------------------- /09-Data-Structures-Operators/starter/coding-chellenge-1.js: -------------------------------------------------------------------------------- 1 | // We're building a football betting app (soccer for my American friends 😅)! 2 | 3 | // Suppose we get data from a web service about a certain game (below). In this challenge we're gonna work with the data. So here are your tasks: 4 | 5 | // 1. Create one player array for each team (variables 'players1' and 'players2') 6 | // 2. The first player in any player array is the goalkeeper and the others are field players. For Bayern Munich (team 1) create one variable ('gk') with the goalkeeper's name, and one array ('fieldPlayers') with all the remaining 10 field players 7 | // 3. Create an array 'allPlayers' containing all players of both teams (22 players) 8 | // 4. During the game, Bayern Munich (team 1) used 3 substitute players. So create a new array ('players1Final') containing all the original team1 players plus 'Thiago', 'Coutinho' and 'Perisic' 9 | // 5. Based on the game.odds object, create one variable for each odd (called 'team1', 'draw' and 'team2') 10 | // 6. Write a function ('printGoals') that receives an arbitrary number of player names (NOT an array) and prints each of them to the console, along with the number of goals that were scored in total (number of player names passed in) 11 | // 7. The team with the lower odd is more likely to win. Print to the console which team is more likely to win, WITHOUT using an if/else statement or the ternary operator. 12 | 13 | // TEST DATA FOR 6: Use players 'Davies', 'Muller', 'Lewandowski' and 'Kimmich'. 14 | // Then, call the function again with players from game.scored 15 | 16 | const game = { 17 | team1: 'Bayern Munich', 18 | team2: 'Borrussia Dortmund', 19 | players: [ 20 | [ 21 | 'Neuer', 22 | 'Pavard', 23 | 'Martinez', 24 | 'Alaba', 25 | 'Davies', 26 | 'Kimmich', 27 | 'Goretzka', 28 | 'Coman', 29 | 'Muller', 30 | 'Gnarby', 31 | 'Lewandowski', 32 | ], 33 | [ 34 | 'Burki', 35 | 'Schulz', 36 | 'Hummels', 37 | 'Akanji', 38 | 'Hakimi', 39 | 'Weigl', 40 | 'Witsel', 41 | 'Hazard', 42 | 'Brandt', 43 | 'Sancho', 44 | 'Gotze', 45 | ], 46 | ], 47 | score: '4:0', 48 | scored: ['Lewandowski', 'Gnarby', 'Lewandowski', 'Hummels'], 49 | date: 'Nov 9th, 2037', 50 | odds: { 51 | team1: 1.33, 52 | x: 3.25, 53 | team2: 6.5, 54 | }, 55 | }; 56 | 57 | // 1 58 | const [players1, players2] = game.players; 59 | // console.log(players1, players2); 60 | 61 | // 2 62 | const [gk, ...fieldPlayers] = players1; 63 | // console.log(gk, fieldPlayers); 64 | 65 | // 3 66 | const allPlayers = [...players1, ...players2]; 67 | // console.log(allPlayers); 68 | 69 | // 4 70 | const players1Final = [...players1, 'Thiago', 'Coutinho', 'Perisic']; 71 | // console.log(players1Final); 72 | 73 | // 5 74 | const { team1, x: draw, team2 } = game.odds; 75 | // console.log(team1, draw, team2); 76 | 77 | // 6 78 | const printGoals = (...players) => { 79 | console.log(`${players}, ${players.length}`); 80 | }; 81 | 82 | // printGoals('Davies', 'Muller', 'Lewandowski', 'Kimmich'); 83 | 84 | // 7 85 | team1 < team2 && console.log('team 1 wins'); 86 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/11-Arrays-Bankist/final/Bankist-flowchart.png -------------------------------------------------------------------------------- /11-Arrays-Bankist/final/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/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/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/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/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/11-Arrays-Bankist/starter/Bankist-flowchart.png -------------------------------------------------------------------------------- /11-Arrays-Bankist/starter/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/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/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/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/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/12-Numbers-Dates-Timers-Bankist/final/Bankist-flowchart.png -------------------------------------------------------------------------------- /12-Numbers-Dates-Timers-Bankist/final/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/12-Numbers-Dates-Timers-Bankist/final/icon.png -------------------------------------------------------------------------------- /12-Numbers-Dates-Timers-Bankist/final/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/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/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/12-Numbers-Dates-Timers-Bankist/starter/Bankist-flowchart.png -------------------------------------------------------------------------------- /12-Numbers-Dates-Timers-Bankist/starter/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/12-Numbers-Dates-Timers-Bankist/starter/icon.png -------------------------------------------------------------------------------- /12-Numbers-Dates-Timers-Bankist/starter/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/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/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/final/img/card-lazy.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/card.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/final/img/card.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/digital-lazy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/final/img/digital-lazy.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/digital.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/final/img/digital.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/grow-lazy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/final/img/grow-lazy.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/grow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/final/img/grow.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/final/img/hero.png -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/final/img/icon.png -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/img-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/final/img/img-1.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/img-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/final/img/img-2.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/img-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/final/img/img-3.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/img-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/final/img/img-4.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/final/img/logo.png -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/user-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/final/img/user-1.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/user-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/final/img/user-2.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/final/img/user-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/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/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/starter/img/card-lazy.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/card.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/starter/img/card.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/digital-lazy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/starter/img/digital-lazy.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/digital.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/starter/img/digital.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/grow-lazy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/starter/img/grow-lazy.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/grow.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/starter/img/grow.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/starter/img/hero.png -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/starter/img/icon.png -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/img-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/starter/img/img-1.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/img-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/starter/img/img-2.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/img-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/starter/img/img-3.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/img-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/starter/img/img-4.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/starter/img/logo.png -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/user-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/starter/img/user-1.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/user-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/13-Advanced-DOM-Bankist/starter/img/user-2.jpg -------------------------------------------------------------------------------- /13-Advanced-DOM-Bankist/starter/img/user-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/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/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/15-Mapty/final/Mapty-architecture-final.png -------------------------------------------------------------------------------- /15-Mapty/final/Mapty-architecture-part-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/15-Mapty/final/Mapty-architecture-part-1.png -------------------------------------------------------------------------------- /15-Mapty/final/Mapty-flowchart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/15-Mapty/final/Mapty-flowchart.png -------------------------------------------------------------------------------- /15-Mapty/final/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/15-Mapty/final/icon.png -------------------------------------------------------------------------------- /15-Mapty/final/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/15-Mapty/final/logo.png -------------------------------------------------------------------------------- /15-Mapty/final/other.js: -------------------------------------------------------------------------------- 1 | const firstName = 'Jonas'; 2 | console.log(months); 3 | -------------------------------------------------------------------------------- /15-Mapty/starter/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /15-Mapty/starter/Mapty-architecture-final.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/15-Mapty/starter/Mapty-architecture-final.png -------------------------------------------------------------------------------- /15-Mapty/starter/Mapty-architecture-part-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/15-Mapty/starter/Mapty-architecture-part-1.png -------------------------------------------------------------------------------- /15-Mapty/starter/Mapty-flowchart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/15-Mapty/starter/Mapty-flowchart.png -------------------------------------------------------------------------------- /15-Mapty/starter/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/15-Mapty/starter/icon.png -------------------------------------------------------------------------------- /15-Mapty/starter/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/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 | -------------------------------------------------------------------------------- /16-Asynchronous/final/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "arrowParens": "avoid" 4 | } 5 | -------------------------------------------------------------------------------- /16-Asynchronous/final/img/img-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/16-Asynchronous/final/img/img-1.jpg -------------------------------------------------------------------------------- /16-Asynchronous/final/img/img-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/16-Asynchronous/final/img/img-2.jpg -------------------------------------------------------------------------------- /16-Asynchronous/final/img/img-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/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/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/16-Asynchronous/starter/img/img-1.jpg -------------------------------------------------------------------------------- /16-Asynchronous/starter/img/img-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/16-Asynchronous/starter/img/img-2.jpg -------------------------------------------------------------------------------- /16-Asynchronous/starter/img/img-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/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 | const shoppingCart = [ 2 | { product: 'bread', quantity: 6 }, 3 | { product: 'pizza', quantity: 2 }, 4 | { product: 'milk', quantity: 4 }, 5 | { product: 'water', quantity: 10 }, 6 | ]; 7 | 8 | const allowedProducts = { 9 | lisbon: 5, 10 | others: 7, 11 | }; 12 | 13 | const checkCorrectAllowedProducts = function (cart, numAllowed, city) { 14 | if (!cart.length) return []; 15 | 16 | // const allowed = numAllowed[city] > 0 ? numAllowed[city] : numAllowed.others; 17 | const allowed = numAllowed?.[city] ?? allowedProducts.others; 18 | 19 | const newCart = cart.map(item => { 20 | const { product, quantity } = item; 21 | return { 22 | product, 23 | quantity: quantity > allowed ? allowed : quantity, 24 | }; 25 | }); 26 | 27 | return newCart; 28 | }; 29 | const allowedShoppingCart = checkCorrectAllowedProducts( 30 | shoppingCart, 31 | allowedProducts, 32 | 'lisbon' 33 | // 'faro' 34 | ); 35 | console.log(allowedShoppingCart); 36 | 37 | const createOrderDescription = function (cart) { 38 | const [{ product: p, quantity: q }] = cart; 39 | 40 | return `Order with ${q} ${p}${cart.length > 1 ? ', etc...' : '.'}`; 41 | }; 42 | const orderDescription = createOrderDescription(allowedShoppingCart); 43 | 44 | console.log(orderDescription); 45 | -------------------------------------------------------------------------------- /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 sc = [ 2 | { product: 'bread', quantity: 6 }, 3 | { product: 'pizza', quantity: 2 }, 4 | { product: 'milk', quantity: 4 }, 5 | { product: 'water', quantity: 10 }, 6 | ]; 7 | 8 | var allow = { 9 | lisbon: 5, 10 | others: 7, 11 | }; 12 | 13 | var description = ''; 14 | 15 | var check = function (city) { 16 | if (sc.length > 0) { 17 | var allowed; 18 | if (city == 'lisbon') { 19 | allowed = allow.lisbon; 20 | } else { 21 | allowed = allow.others; 22 | } 23 | 24 | for (item of sc) { 25 | if (item.quantity > allowed) item.quantity = allowed; 26 | } 27 | } 28 | }; 29 | check('lisbon'); 30 | console.log(sc); 31 | 32 | var createDescription = function () { 33 | var first = sc[0]; 34 | var p = first.product; 35 | var q = first.quantity; 36 | 37 | if (sc.length > 1) { 38 | description = 'Order with ' + q + ' ' + p + ', etc...'; 39 | } else { 40 | description = 'Order with ' + q + ' ' + p + '.'; 41 | } 42 | }; 43 | createDescription(); 44 | 45 | console.log(description); 46 | -------------------------------------------------------------------------------- /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/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/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/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/18-forkify/final/src/img/favicon.png -------------------------------------------------------------------------------- /18-forkify/final/src/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/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/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/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/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/18-forkify/starter/forkify-architecture-recipe-loading.png -------------------------------------------------------------------------------- /18-forkify/starter/forkify-flowchart-part-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/18-forkify/starter/forkify-flowchart-part-1.png -------------------------------------------------------------------------------- /18-forkify/starter/forkify-flowchart-part-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/18-forkify/starter/forkify-flowchart-part-2.png -------------------------------------------------------------------------------- /18-forkify/starter/forkify-flowchart-part-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/18-forkify/starter/forkify-flowchart-part-3.png -------------------------------------------------------------------------------- /18-forkify/starter/src/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/18-forkify/starter/src/img/favicon.png -------------------------------------------------------------------------------- /18-forkify/starter/src/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/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, 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 keep mentioning 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: Do you accept pull requests? 66 | 67 | **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. 68 | -------------------------------------------------------------------------------- /course-material-v2.0/all-coding-challenges.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/course-material-v2.0/all-coding-challenges.pdf -------------------------------------------------------------------------------- /course-material-v2.0/assignments-js-fundamentals.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/course-material-v2.0/assignments-js-fundamentals.pdf -------------------------------------------------------------------------------- /course-material-v2.0/theory-lectures-v2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/georginapuig/complete-javascript-course/e05bbe24992f31ddfc361338a8ee69265069fec1/course-material-v2.0/theory-lectures-v2.pdf --------------------------------------------------------------------------------