├── .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 |
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 | Again!
15 | ?
16 |
17 |
18 |
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 | Again!
15 | ?
16 |
17 |
18 |
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 | Again!
15 | ?
16 |
17 |
18 |
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 | Show modal 1
12 | Show modal 2
13 | Show modal 3
14 |
15 |
16 |
×
17 |
I'm a modal window 😍
18 |
19 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
20 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
21 | veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
22 | commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
23 | velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
24 | occaecat cupidatat non proident, sunt in culpa qui officia deserunt
25 | mollit anim id est laborum.
26 |
27 |
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 | Show modal 1
12 | Show modal 2
13 | Show modal 3
14 |
15 |
16 |
×
17 |
I'm a modal window 😍
18 |
19 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
20 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
21 | veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
22 | commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
23 | velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
24 | occaecat cupidatat non proident, sunt in culpa qui officia deserunt
25 | mollit anim id est laborum.
26 |
27 |
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 | Show modal 1
12 | Show modal 2
13 | Show modal 3
14 |
15 |
16 |
×
17 |
I'm a modal window 😍
18 |
19 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
20 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
21 | veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
22 | commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
23 | velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
24 | occaecat cupidatat non proident, sunt in culpa qui officia deserunt
25 | mollit anim id est laborum.
26 |
27 |
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 |
19 |
20 |
21 | Player 2
22 | 24
23 |
27 |
28 |
29 |
30 | 🔄 New game
31 | 🎲 Roll dice
32 | 📥 Hold
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 |
19 |
20 |
21 | Player 2
22 | 24
23 |
27 |
28 |
29 |
30 | 🔄 New game
31 | 🎲 Roll dice
32 | 📥 Hold
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 |
19 |
20 |
21 | Player 2
22 | 24
23 |
27 |
28 |
29 |
30 | 🔄 New game
31 | 🎲 Roll dice
32 | 📥 Hold
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 | Buy new plane 🛩
42 | Answer poll ⁉️
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 | Buy new plane 🛩
42 | Answer poll ⁉️
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 |
20 | Log in to get started
21 |
22 |
37 |
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 |
↓ SORT
76 |
77 |
78 |
79 |
80 |
Transfer money
81 |
88 |
89 |
90 |
91 |
92 |
Request loan
93 |
98 |
99 |
100 |
101 |
102 |
Close account
103 |
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 |
20 | Log in to get started
21 |
22 |
37 |
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 |
↓ SORT
76 |
77 |
78 |
79 |
80 |
Transfer money
81 |
88 |
89 |
90 |
91 |
92 |
Request loan
93 |
98 |
99 |
100 |
101 |
102 |
Close account
103 |
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 |
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
--------------------------------------------------------------------------------