├── 01-Fundamentals-Part-1
├── final
│ ├── index.html
│ └── script.js
└── starter
│ └── index.html
├── 02-Fundamentals-Part-2
├── final
│ ├── index.html
│ └── script.js
└── starter
│ ├── index.html
│ └── script.js
├── 03-Developer-Skills
├── final
│ ├── .prettierrc
│ ├── index.html
│ └── script.js
└── starter
│ ├── index.html
│ └── script.js
├── 04-HTML-CSS
└── final
│ ├── index.html
│ └── style.css
├── 05-Guess-My-Number
├── final
│ ├── .prettierrc
│ ├── index.html
│ ├── script.js
│ └── style.css
└── starter
│ ├── .prettierrc
│ ├── index.html
│ ├── script.js
│ └── style.css
├── 06-Modal
├── final
│ ├── .prettierrc
│ ├── index.html
│ ├── script.js
│ └── style.css
└── starter
│ ├── .prettierrc
│ ├── index.html
│ ├── script.js
│ └── style.css
├── 07-Pig-Game
├── final
│ ├── .prettierrc
│ ├── dice-1.png
│ ├── dice-2.png
│ ├── dice-3.png
│ ├── dice-4.png
│ ├── dice-5.png
│ ├── dice-6.png
│ ├── index.html
│ ├── pig-game-flowchart.png
│ ├── script.js
│ └── style.css
└── starter
│ ├── .prettierrc
│ ├── dice-1.png
│ ├── dice-2.png
│ ├── dice-3.png
│ ├── dice-4.png
│ ├── dice-5.png
│ ├── dice-6.png
│ ├── index.html
│ ├── pig-game-flowchart.png
│ ├── script.js
│ └── style.css
├── 08-Behind-the-Scenes
├── final
│ ├── .prettierrc
│ ├── index.html
│ └── script.js
└── starter
│ ├── .prettierrc
│ ├── index.html
│ └── script.js
├── 09-Data-Structures-Operators
├── final
│ ├── .prettierrc
│ ├── index.html
│ └── script.js
└── starter
│ ├── .prettierrc
│ ├── index.html
│ └── script.js
├── 10-Functions
├── final
│ ├── .prettierrc
│ ├── index.html
│ └── script.js
└── starter
│ ├── .prettierrc
│ ├── index.html
│ └── script.js
├── 11-Arrays-Bankist
├── final
│ ├── .prettierrc
│ ├── Bankist-flowchart.png
│ ├── icon.png
│ ├── index.html
│ ├── logo.png
│ ├── script.js
│ └── style.css
└── starter
│ ├── .prettierrc
│ ├── Bankist-flowchart.png
│ ├── icon.png
│ ├── index.html
│ ├── logo.png
│ ├── script.js
│ └── style.css
├── 12-Numbers-Dates-Timers-Bankist
├── final
│ ├── .prettierrc
│ ├── Bankist-flowchart.png
│ ├── icon.png
│ ├── index.html
│ ├── logo.png
│ ├── script.js
│ └── style.css
└── starter
│ ├── .prettierrc
│ ├── Bankist-flowchart.png
│ ├── icon.png
│ ├── index.html
│ ├── logo.png
│ ├── script.js
│ └── style.css
├── 13-Advanced-DOM-Bankist
├── final
│ ├── .prettierrc
│ ├── img
│ │ ├── card-lazy.jpg
│ │ ├── card.jpg
│ │ ├── digital-lazy.jpg
│ │ ├── digital.jpg
│ │ ├── grow-lazy.jpg
│ │ ├── grow.jpg
│ │ ├── hero.png
│ │ ├── icon.png
│ │ ├── icons.svg
│ │ ├── img-1.jpg
│ │ ├── img-2.jpg
│ │ ├── img-3.jpg
│ │ ├── img-4.jpg
│ │ ├── logo.png
│ │ ├── user-1.jpg
│ │ ├── user-2.jpg
│ │ └── user-3.jpg
│ ├── index.html
│ ├── script.js
│ └── style.css
└── starter
│ ├── .prettierrc
│ ├── img
│ ├── card-lazy.jpg
│ ├── card.jpg
│ ├── digital-lazy.jpg
│ ├── digital.jpg
│ ├── grow-lazy.jpg
│ ├── grow.jpg
│ ├── hero.png
│ ├── icon.png
│ ├── icons.svg
│ ├── img-1.jpg
│ ├── img-2.jpg
│ ├── img-3.jpg
│ ├── img-4.jpg
│ ├── logo.png
│ ├── user-1.jpg
│ ├── user-2.jpg
│ └── user-3.jpg
│ ├── index.html
│ ├── script.js
│ └── style.css
├── 14-OOP
├── final
│ ├── .prettierrc
│ ├── index.html
│ └── script.js
└── starter
│ ├── .prettierrc
│ ├── index.html
│ └── script.js
├── 15-Mapty
├── final
│ ├── .prettierrc
│ ├── Mapty-architecture-final.png
│ ├── Mapty-architecture-part-1.png
│ ├── Mapty-flowchart.png
│ ├── icon.png
│ ├── index.html
│ ├── logo.png
│ ├── other.js
│ ├── script.js
│ └── style.css
└── starter
│ ├── .prettierrc
│ ├── Mapty-architecture-final.png
│ ├── Mapty-architecture-part-1.png
│ ├── Mapty-flowchart.png
│ ├── icon.png
│ ├── index.html
│ ├── logo.png
│ ├── script.js
│ └── style.css
├── 16-Asynchronous
├── final
│ ├── .prettierrc
│ ├── img
│ │ ├── img-1.jpg
│ │ ├── img-2.jpg
│ │ └── img-3.jpg
│ ├── index.html
│ ├── script.js
│ └── style.css
└── starter
│ ├── .prettierrc
│ ├── img
│ ├── img-1.jpg
│ ├── img-2.jpg
│ └── img-3.jpg
│ ├── index.html
│ ├── script.js
│ └── style.css
├── 17-Modern-JS-Modules-Tooling
├── final
│ ├── .prettierrc
│ ├── clean.js
│ ├── dist
│ │ ├── index.html
│ │ ├── index.js
│ │ ├── index.js.map
│ │ ├── script.0b6e4fd3.js
│ │ ├── script.0b6e4fd3.js.map
│ │ ├── script.75da7f30.js
│ │ └── script.75da7f30.js.map
│ ├── index.html
│ ├── package-lock.json
│ ├── package.json
│ ├── script.js
│ └── shoppingCart.js
└── starter
│ ├── .prettierrc
│ ├── clean.js
│ ├── index.html
│ └── script.js
├── 18-forkify
├── final
│ ├── .gitignore
│ ├── .prettierrc
│ ├── README.md
│ ├── index.html
│ ├── package-lock.json
│ ├── package.json
│ └── src
│ │ ├── img
│ │ ├── favicon.png
│ │ ├── icons.svg
│ │ └── logo.png
│ │ ├── js
│ │ ├── config.js
│ │ ├── controller.js
│ │ ├── helpers.js
│ │ ├── model.js
│ │ └── views
│ │ │ ├── View.js
│ │ │ ├── addRecipeView.js
│ │ │ ├── bookmarksView.js
│ │ │ ├── paginationView.js
│ │ │ ├── previewView.js
│ │ │ ├── recipeView.js
│ │ │ ├── resultsView.js
│ │ │ └── searchView.js
│ │ └── sass
│ │ ├── _base.scss
│ │ ├── _components.scss
│ │ ├── _header.scss
│ │ ├── _preview.scss
│ │ ├── _recipe.scss
│ │ ├── _searchResults.scss
│ │ ├── _upload.scss
│ │ └── main.scss
└── starter
│ ├── .prettierrc
│ ├── forkify-architecture-recipe-loading.png
│ ├── forkify-flowchart-part-1.png
│ ├── forkify-flowchart-part-2.png
│ ├── forkify-flowchart-part-3.png
│ ├── index.html
│ └── src
│ ├── img
│ ├── favicon.png
│ ├── icons.svg
│ └── logo.png
│ ├── js
│ └── controller.js
│ └── sass
│ ├── _base.scss
│ ├── _components.scss
│ ├── _header.scss
│ ├── _preview.scss
│ ├── _recipe.scss
│ ├── _searchResults.scss
│ ├── _upload.scss
│ └── main.scss
└── README.md
/01-Fundamentals-Part-1/final/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | JavaScript Fundamentals – Part 1
8 |
25 |
26 |
27 | JavaScript Fundamentals – Part 1
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/01-Fundamentals-Part-1/starter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | JavaScript Fundamentals – Part 1
8 |
25 |
26 |
27 | JavaScript Fundamentals – Part 1
28 |
29 |
30 |
--------------------------------------------------------------------------------
/02-Fundamentals-Part-2/final/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | JavaScript Fundamentals – Part 2
8 |
25 |
26 |
27 | JavaScript Fundamentals – Part 2
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/02-Fundamentals-Part-2/starter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | JavaScript Fundamentals – Part 2
8 |
25 |
26 |
27 | JavaScript Fundamentals – Part 2
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/02-Fundamentals-Part-2/starter/script.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/02-Fundamentals-Part-2/starter/script.js
--------------------------------------------------------------------------------
/03-Developer-Skills/final/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/03-Developer-Skills/final/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Developer Skills & Editor Setup
8 |
25 |
26 |
27 | Developer Skills & Editor Setup
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/03-Developer-Skills/final/script.js:
--------------------------------------------------------------------------------
1 | // Remember, we're gonna use strict mode in all scripts now!
2 | 'use strict';
3 |
4 | /*
5 | ///////////////////////////////////////
6 | // Using Google, StackOverflow and MDN
7 |
8 | // PROBLEM 1:
9 | // We work for a company building a smart home thermometer. Our most recent task is this: "Given an array of temperatures of one day, calculate the temperature amplitude. Keep in mind that sometimes there might be a sensor error."
10 |
11 | const temperatures = [3, -2, -6, -1, 'error', 9, 13, 17, 15, 14, 9, 5];
12 |
13 | // 1) Understanding the problem
14 | // - What is temp amplitude? Answer: difference between highest and lowest temp
15 | // - How to compute max and min temperatures?
16 | // - What's a sensor error? And what do do?
17 |
18 | // 2) Breaking up into sub-problems
19 | // - How to ignore errors?
20 | // - Find max value in temp array
21 | // - Find min value in temp array
22 | // - Subtract min from max (amplitude) and return it
23 |
24 | const calcTempAmplitude = function (temps) {
25 | let max = temps[0];
26 | let min = temps[0];
27 |
28 | for (let i = 0; i < temps.length; i++) {
29 | const curTemp = temps[i];
30 | if (typeof curTemp !== 'number') continue;
31 |
32 | if (curTemp > max) max = curTemp;
33 | if (curTemp < min) min = curTemp;
34 | }
35 | console.log(max, min);
36 | return max - min;
37 | };
38 | const amplitude = calcTempAmplitude(temperatures);
39 | console.log(amplitude);
40 |
41 | // PROBLEM 2:
42 | // Function should now receive 2 arrays of temps
43 |
44 | // 1) Understanding the problem
45 | // - With 2 arrays, should we implement functionality twice? NO! Just merge two arrays
46 |
47 | // 2) Breaking up into sub-problems
48 | // - Merge 2 arrays
49 |
50 | const calcTempAmplitudeNew = function (t1, t2) {
51 | const temps = t1.concat(t2);
52 | console.log(temps);
53 |
54 | let max = temps[0];
55 | let min = temps[0];
56 |
57 | for (let i = 0; i < temps.length; i++) {
58 | const curTemp = temps[i];
59 | if (typeof curTemp !== 'number') continue;
60 |
61 | if (curTemp > max) max = curTemp;
62 | if (curTemp < min) min = curTemp;
63 | }
64 | console.log(max, min);
65 | return max - min;
66 | };
67 | const amplitudeNew = calcTempAmplitudeNew([3, 5, 1], [9, 0, 5]);
68 | console.log(amplitudeNew);
69 |
70 |
71 | ///////////////////////////////////////
72 | // Debugging with the Console and Breakpoints
73 | const measureKelvin = function () {
74 | const measurement = {
75 | type: 'temp',
76 | unit: 'celsius',
77 |
78 | // C) FIX
79 | // value: Number(prompt('Degrees celsius:')),
80 | value: 10,
81 | };
82 |
83 | // B) FIND
84 | console.table(measurement);
85 |
86 | // console.log(measurement.value);
87 | // console.warn(measurement.value);
88 | // console.error(measurement.value);
89 |
90 | const kelvin = measurement.value + 273;
91 | return kelvin;
92 | };
93 | // A) IDENTIFY
94 | console.log(measureKelvin());
95 |
96 | // Using a debugger
97 | const calcTempAmplitudeBug = function (t1, t2) {
98 | const temps = t1.concat(t2);
99 | console.log(temps);
100 |
101 | let max = 0;
102 | let min = 0;
103 |
104 | for (let i = 0; i < temps.length; i++) {
105 | const curTemp = temps[i];
106 | if (typeof curTemp !== 'number') continue;
107 |
108 | if (curTemp > max) max = curTemp;
109 | if (curTemp < min) min = curTemp;
110 | }
111 | console.log(max, min);
112 | return max - min;
113 | };
114 | const amplitudeBug = calcTempAmplitudeBug([3, 5, 1], [9, 4, 5]);
115 | // A) IDENTIFY
116 | console.log(amplitudeBug);
117 | */
118 |
119 | ///////////////////////////////////////
120 | // Coding Challenge #1
121 |
122 | /*
123 | Given an array of forecasted maximum temperatures, the thermometer displays a string with these temperatures.
124 |
125 | Example: [17, 21, 23] will print "... 17ºC in 1 days ... 21ºC in 2 days ... 23ºC in 3 days ..."
126 |
127 | Create a function 'printForecast' which takes in an array 'arr' and logs a string like the above to the console.
128 |
129 | Use the problem-solving framework: Understand the problem and break it up into sub-problems!
130 |
131 | TEST DATA 1: [17, 21, 23]
132 | TEST DATA 2: [12, 5, -5, 0, 4]
133 | */
134 |
135 | /*
136 | // 1) Understanding the problem
137 | // - Array transformed to string, separated by ...
138 | // - What is the X days? Answer: index + 1
139 |
140 | // 2) Breaking up into sub-problems
141 | // - Transform array into string
142 | // - Transform each element to string with ºC
143 | // - Strings needs to contain day (index + 1)
144 | // - Add ... between elements and start and end of string
145 | // - Log string to console
146 |
147 | const data1 = [17, 21, 23];
148 | const data2 = [12, 5, -5, 0, 4];
149 |
150 | console.log(`... ${data1[0]}ºC ... ${data1[1]}ºC ... ${data1[2]}ºC ...`);
151 |
152 | const printForecast = function (arr) {
153 | let str = '';
154 | for (let i = 0; i < arr.length; i++) {
155 | str += `${arr[i]}ºC in ${i + 1} days ... `;
156 | }
157 | console.log('...' + str);
158 | };
159 | printForecast(data1);
160 | */
161 |
162 |
--------------------------------------------------------------------------------
/03-Developer-Skills/starter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Developer Skills & Editor Setup
8 |
25 |
26 |
27 | Developer Skills & Editor Setup
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/03-Developer-Skills/starter/script.js:
--------------------------------------------------------------------------------
1 | // Remember, we're gonna use strict mode in all scripts now!
2 | 'use strict';
3 |
4 |
--------------------------------------------------------------------------------
/04-HTML-CSS/final/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Learning HTML & CSS
10 |
11 |
12 | JavaScript is fun, but so is HTML & CSS!
13 |
14 | You can learn JavaScript without HTML and CSS, but for DOM manipulation
15 | it's useful to have some basic ideas of HTML & CSS. You can learn more
16 | about it
17 | on Udemy .
18 |
19 |
20 | Another heading
21 |
22 | Just another paragraph
23 |
24 |
25 |
29 |
30 |
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/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/07-Pig-Game/final/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/07-Pig-Game/final/dice-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/final/dice-1.png
--------------------------------------------------------------------------------
/07-Pig-Game/final/dice-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/final/dice-2.png
--------------------------------------------------------------------------------
/07-Pig-Game/final/dice-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/final/dice-3.png
--------------------------------------------------------------------------------
/07-Pig-Game/final/dice-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/final/dice-4.png
--------------------------------------------------------------------------------
/07-Pig-Game/final/dice-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/final/dice-5.png
--------------------------------------------------------------------------------
/07-Pig-Game/final/dice-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/final/dice-6.png
--------------------------------------------------------------------------------
/07-Pig-Game/final/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Pig Game
9 |
10 |
11 |
12 |
13 | Player 1
14 | 43
15 |
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/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/final/pig-game-flowchart.png
--------------------------------------------------------------------------------
/07-Pig-Game/final/script.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // Selecting elements
4 | const player0El = document.querySelector('.player--0');
5 | const player1El = document.querySelector('.player--1');
6 | const score0El = document.querySelector('#score--0');
7 | const score1El = document.getElementById('score--1');
8 | const current0El = document.getElementById('current--0');
9 | const current1El = document.getElementById('current--1');
10 |
11 | const diceEl = document.querySelector('.dice');
12 | const btnNew = document.querySelector('.btn--new');
13 | const btnRoll = document.querySelector('.btn--roll');
14 | const btnHold = document.querySelector('.btn--hold');
15 |
16 | let scores, currentScore, activePlayer, playing;
17 |
18 | // Starting conditions
19 | const init = function () {
20 | scores = [0, 0];
21 | currentScore = 0;
22 | activePlayer = 0;
23 | playing = true;
24 |
25 | score0El.textContent = 0;
26 | score1El.textContent = 0;
27 | current0El.textContent = 0;
28 | current1El.textContent = 0;
29 |
30 | diceEl.classList.add('hidden');
31 | player0El.classList.remove('player--winner');
32 | player1El.classList.remove('player--winner');
33 | player0El.classList.add('player--active');
34 | player1El.classList.remove('player--active');
35 | };
36 | init();
37 |
38 | const switchPlayer = function () {
39 | document.getElementById(`current--${activePlayer}`).textContent = 0;
40 | currentScore = 0;
41 | activePlayer = activePlayer === 0 ? 1 : 0;
42 | player0El.classList.toggle('player--active');
43 | player1El.classList.toggle('player--active');
44 | };
45 |
46 | // Rolling dice functionality
47 | btnRoll.addEventListener('click', function () {
48 | if (playing) {
49 | // 1. Generating a random dice roll
50 | const dice = Math.trunc(Math.random() * 6) + 1;
51 |
52 | // 2. Display dice
53 | diceEl.classList.remove('hidden');
54 | diceEl.src = `dice-${dice}.png`;
55 |
56 | // 3. Check for rolled 1
57 | if (dice !== 1) {
58 | // Add dice to current score
59 | currentScore += dice;
60 | document.getElementById(
61 | `current--${activePlayer}`
62 | ).textContent = currentScore;
63 | } else {
64 | // Switch to next player
65 | switchPlayer();
66 | }
67 | }
68 | });
69 |
70 | btnHold.addEventListener('click', function () {
71 | if (playing) {
72 | // 1. Add current score to active player's score
73 | scores[activePlayer] += currentScore;
74 | // scores[1] = scores[1] + currentScore
75 |
76 | document.getElementById(`score--${activePlayer}`).textContent =
77 | scores[activePlayer];
78 |
79 | // 2. Check if player's score is >= 100
80 | if (scores[activePlayer] >= 100) {
81 | // Finish the game
82 | playing = false;
83 | diceEl.classList.add('hidden');
84 |
85 | document
86 | .querySelector(`.player--${activePlayer}`)
87 | .classList.add('player--winner');
88 | document
89 | .querySelector(`.player--${activePlayer}`)
90 | .classList.remove('player--active');
91 | } else {
92 | // Switch to the next player
93 | switchPlayer();
94 | }
95 | }
96 | });
97 |
98 | btnNew.addEventListener('click', init);
99 |
--------------------------------------------------------------------------------
/07-Pig-Game/final/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Nunito&display=swap');
2 |
3 | * {
4 | margin: 0;
5 | padding: 0;
6 | box-sizing: inherit;
7 | }
8 |
9 | html {
10 | font-size: 62.5%;
11 | box-sizing: border-box;
12 | }
13 |
14 | body {
15 | font-family: 'Nunito', sans-serif;
16 | font-weight: 400;
17 | height: 100vh;
18 | color: #333;
19 | background-image: linear-gradient(to top left, #753682 0%, #bf2e34 100%);
20 | display: flex;
21 | align-items: center;
22 | justify-content: center;
23 | }
24 |
25 | /* LAYOUT */
26 | main {
27 | position: relative;
28 | width: 100rem;
29 | height: 60rem;
30 | background-color: rgba(255, 255, 255, 0.35);
31 | backdrop-filter: blur(200px);
32 | filter: blur();
33 | box-shadow: 0 3rem 5rem rgba(0, 0, 0, 0.25);
34 | border-radius: 9px;
35 | overflow: hidden;
36 | display: flex;
37 | }
38 |
39 | .player {
40 | flex: 50%;
41 | padding: 9rem;
42 | display: flex;
43 | flex-direction: column;
44 | align-items: center;
45 | transition: all 0.75s;
46 | }
47 |
48 | /* ELEMENTS */
49 | .name {
50 | position: relative;
51 | font-size: 4rem;
52 | text-transform: uppercase;
53 | letter-spacing: 1px;
54 | word-spacing: 2px;
55 | font-weight: 300;
56 | margin-bottom: 1rem;
57 | }
58 |
59 | .score {
60 | font-size: 8rem;
61 | font-weight: 300;
62 | color: #c7365f;
63 | margin-bottom: auto;
64 | }
65 |
66 | .player--active {
67 | background-color: rgba(255, 255, 255, 0.4);
68 | }
69 | .player--active .name {
70 | font-weight: 700;
71 | }
72 | .player--active .score {
73 | font-weight: 400;
74 | }
75 |
76 | .player--active .current {
77 | opacity: 1;
78 | }
79 |
80 | .current {
81 | background-color: #c7365f;
82 | opacity: 0.8;
83 | border-radius: 9px;
84 | color: #fff;
85 | width: 65%;
86 | padding: 2rem;
87 | text-align: center;
88 | transition: all 0.75s;
89 | }
90 |
91 | .current-label {
92 | text-transform: uppercase;
93 | margin-bottom: 1rem;
94 | font-size: 1.7rem;
95 | color: #ddd;
96 | }
97 |
98 | .current-score {
99 | font-size: 3.5rem;
100 | }
101 |
102 | /* ABSOLUTE POSITIONED ELEMENTS */
103 | .btn {
104 | position: absolute;
105 | left: 50%;
106 | transform: translateX(-50%);
107 | color: #444;
108 | background: none;
109 | border: none;
110 | font-family: inherit;
111 | font-size: 1.8rem;
112 | text-transform: uppercase;
113 | cursor: pointer;
114 | font-weight: 400;
115 | transition: all 0.2s;
116 |
117 | background-color: white;
118 | background-color: rgba(255, 255, 255, 0.6);
119 | backdrop-filter: blur(10px);
120 |
121 | padding: 0.7rem 2.5rem;
122 | border-radius: 50rem;
123 | box-shadow: 0 1.75rem 3.5rem rgba(0, 0, 0, 0.1);
124 | }
125 |
126 | .btn::first-letter {
127 | font-size: 2.4rem;
128 | display: inline-block;
129 | margin-right: 0.7rem;
130 | }
131 |
132 | .btn--new {
133 | top: 4rem;
134 | }
135 | .btn--roll {
136 | top: 39.3rem;
137 | }
138 | .btn--hold {
139 | top: 46.1rem;
140 | }
141 |
142 | .btn:active {
143 | transform: translate(-50%, 3px);
144 | box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.15);
145 | }
146 |
147 | .btn:focus {
148 | outline: none;
149 | }
150 |
151 | .dice {
152 | position: absolute;
153 | left: 50%;
154 | top: 16.5rem;
155 | transform: translateX(-50%);
156 | height: 10rem;
157 | box-shadow: 0 2rem 5rem rgba(0, 0, 0, 0.2);
158 | }
159 |
160 | .player--winner {
161 | background-color: #2f2f2f;
162 | }
163 |
164 | .player--winner .name {
165 | font-weight: 700;
166 | color: #c7365f;
167 | }
168 |
169 | .hidden {
170 | display: none;
171 | }
172 |
--------------------------------------------------------------------------------
/07-Pig-Game/starter/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/07-Pig-Game/starter/dice-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/starter/dice-1.png
--------------------------------------------------------------------------------
/07-Pig-Game/starter/dice-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/starter/dice-2.png
--------------------------------------------------------------------------------
/07-Pig-Game/starter/dice-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/starter/dice-3.png
--------------------------------------------------------------------------------
/07-Pig-Game/starter/dice-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/starter/dice-4.png
--------------------------------------------------------------------------------
/07-Pig-Game/starter/dice-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/starter/dice-5.png
--------------------------------------------------------------------------------
/07-Pig-Game/starter/dice-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/starter/dice-6.png
--------------------------------------------------------------------------------
/07-Pig-Game/starter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Pig Game
9 |
10 |
11 |
12 |
13 | Player 1
14 | 43
15 |
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/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/07-Pig-Game/starter/pig-game-flowchart.png
--------------------------------------------------------------------------------
/07-Pig-Game/starter/script.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
--------------------------------------------------------------------------------
/07-Pig-Game/starter/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Nunito&display=swap');
2 |
3 | * {
4 | margin: 0;
5 | padding: 0;
6 | box-sizing: inherit;
7 | }
8 |
9 | html {
10 | font-size: 62.5%;
11 | box-sizing: border-box;
12 | }
13 |
14 | body {
15 | font-family: 'Nunito', sans-serif;
16 | font-weight: 400;
17 | height: 100vh;
18 | color: #333;
19 | background-image: linear-gradient(to top left, #753682 0%, #bf2e34 100%);
20 | display: flex;
21 | align-items: center;
22 | justify-content: center;
23 | }
24 |
25 | /* LAYOUT */
26 | main {
27 | position: relative;
28 | width: 100rem;
29 | height: 60rem;
30 | background-color: rgba(255, 255, 255, 0.35);
31 | backdrop-filter: blur(200px);
32 | filter: blur();
33 | box-shadow: 0 3rem 5rem rgba(0, 0, 0, 0.25);
34 | border-radius: 9px;
35 | overflow: hidden;
36 | display: flex;
37 | }
38 |
39 | .player {
40 | flex: 50%;
41 | padding: 9rem;
42 | display: flex;
43 | flex-direction: column;
44 | align-items: center;
45 | transition: all 0.75s;
46 | }
47 |
48 | /* ELEMENTS */
49 | .name {
50 | position: relative;
51 | font-size: 4rem;
52 | text-transform: uppercase;
53 | letter-spacing: 1px;
54 | word-spacing: 2px;
55 | font-weight: 300;
56 | margin-bottom: 1rem;
57 | }
58 |
59 | .score {
60 | font-size: 8rem;
61 | font-weight: 300;
62 | color: #c7365f;
63 | margin-bottom: auto;
64 | }
65 |
66 | .player--active {
67 | background-color: rgba(255, 255, 255, 0.4);
68 | }
69 | .player--active .name {
70 | font-weight: 700;
71 | }
72 | .player--active .score {
73 | font-weight: 400;
74 | }
75 |
76 | .player--active .current {
77 | opacity: 1;
78 | }
79 |
80 | .current {
81 | background-color: #c7365f;
82 | opacity: 0.8;
83 | border-radius: 9px;
84 | color: #fff;
85 | width: 65%;
86 | padding: 2rem;
87 | text-align: center;
88 | transition: all 0.75s;
89 | }
90 |
91 | .current-label {
92 | text-transform: uppercase;
93 | margin-bottom: 1rem;
94 | font-size: 1.7rem;
95 | color: #ddd;
96 | }
97 |
98 | .current-score {
99 | font-size: 3.5rem;
100 | }
101 |
102 | /* ABSOLUTE POSITIONED ELEMENTS */
103 | .btn {
104 | position: absolute;
105 | left: 50%;
106 | transform: translateX(-50%);
107 | color: #444;
108 | background: none;
109 | border: none;
110 | font-family: inherit;
111 | font-size: 1.8rem;
112 | text-transform: uppercase;
113 | cursor: pointer;
114 | font-weight: 400;
115 | transition: all 0.2s;
116 |
117 | background-color: white;
118 | background-color: rgba(255, 255, 255, 0.6);
119 | backdrop-filter: blur(10px);
120 |
121 | padding: 0.7rem 2.5rem;
122 | border-radius: 50rem;
123 | box-shadow: 0 1.75rem 3.5rem rgba(0, 0, 0, 0.1);
124 | }
125 |
126 | .btn::first-letter {
127 | font-size: 2.4rem;
128 | display: inline-block;
129 | margin-right: 0.7rem;
130 | }
131 |
132 | .btn--new {
133 | top: 4rem;
134 | }
135 | .btn--roll {
136 | top: 39.3rem;
137 | }
138 | .btn--hold {
139 | top: 46.1rem;
140 | }
141 |
142 | .btn:active {
143 | transform: translate(-50%, 3px);
144 | box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.15);
145 | }
146 |
147 | .btn:focus {
148 | outline: none;
149 | }
150 |
151 | .dice {
152 | position: absolute;
153 | left: 50%;
154 | top: 16.5rem;
155 | transform: translateX(-50%);
156 | height: 10rem;
157 | box-shadow: 0 2rem 5rem rgba(0, 0, 0, 0.2);
158 | }
159 |
160 | .player--winner {
161 | background-color: #2f2f2f;
162 | }
163 |
164 | .player--winner .name {
165 | font-weight: 700;
166 | color: #c7365f;
167 | }
168 |
--------------------------------------------------------------------------------
/08-Behind-the-Scenes/final/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/08-Behind-the-Scenes/final/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | How JavaScript Works Behind the Scenes
8 |
25 |
26 |
27 | How JavaScript Works Behind the Scenes
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/08-Behind-the-Scenes/starter/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/08-Behind-the-Scenes/starter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | How JavaScript Works Behind the Scenes
8 |
25 |
26 |
27 | How JavaScript Works Behind the Scenes
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/08-Behind-the-Scenes/starter/script.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
--------------------------------------------------------------------------------
/09-Data-Structures-Operators/final/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/09-Data-Structures-Operators/final/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Data Structures and Modern Operators
8 |
34 |
35 |
36 | Data Structures and Modern Operators
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/09-Data-Structures-Operators/starter/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/09-Data-Structures-Operators/starter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Data Structures and Modern Operators
8 |
34 |
35 |
36 | Data Structures and Modern Operators
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/09-Data-Structures-Operators/starter/script.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // Data needed for a later exercise
4 | const flights =
5 | '_Delayed_Departure;fao93766109;txl2133758440;11:25+_Arrival;bru0943384722;fao93766109;11:45+_Delayed_Arrival;hel7439299980;fao93766109;12:05+_Departure;fao93766109;lis2323639855;12:30';
6 |
7 | // Data needed for first part of the section
8 | const restaurant = {
9 | name: 'Classico Italiano',
10 | location: 'Via Angelo Tavanti 23, Firenze, Italy',
11 | categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
12 | starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
13 | mainMenu: ['Pizza', 'Pasta', 'Risotto'],
14 |
15 | openingHours: {
16 | thu: {
17 | open: 12,
18 | close: 22,
19 | },
20 | fri: {
21 | open: 11,
22 | close: 23,
23 | },
24 | sat: {
25 | open: 0, // Open 24 hours
26 | close: 24,
27 | },
28 | },
29 | };
30 |
--------------------------------------------------------------------------------
/10-Functions/final/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/10-Functions/final/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | A Closer Look at Functions
8 |
38 |
39 |
40 | A Closer Look at Functions
41 | 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/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/11-Arrays-Bankist/final/Bankist-flowchart.png
--------------------------------------------------------------------------------
/11-Arrays-Bankist/final/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/11-Arrays-Bankist/final/icon.png
--------------------------------------------------------------------------------
/11-Arrays-Bankist/final/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
13 |
14 |
15 | Bankist
16 |
17 |
18 |
19 |
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/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/11-Arrays-Bankist/final/logo.png
--------------------------------------------------------------------------------
/11-Arrays-Bankist/starter/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/11-Arrays-Bankist/starter/Bankist-flowchart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/11-Arrays-Bankist/starter/Bankist-flowchart.png
--------------------------------------------------------------------------------
/11-Arrays-Bankist/starter/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/11-Arrays-Bankist/starter/icon.png
--------------------------------------------------------------------------------
/11-Arrays-Bankist/starter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
13 |
14 |
15 | Bankist
16 |
17 |
18 |
19 |
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/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/11-Arrays-Bankist/starter/logo.png
--------------------------------------------------------------------------------
/11-Arrays-Bankist/starter/script.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /////////////////////////////////////////////////
4 | /////////////////////////////////////////////////
5 | // BANKIST APP
6 |
7 | // Data
8 | const account1 = {
9 | owner: 'Jonas Schmedtmann',
10 | movements: [200, 450, -400, 3000, -650, -130, 70, 1300],
11 | interestRate: 1.2, // %
12 | pin: 1111,
13 | };
14 |
15 | const account2 = {
16 | owner: 'Jessica Davis',
17 | movements: [5000, 3400, -150, -790, -3210, -1000, 8500, -30],
18 | interestRate: 1.5,
19 | pin: 2222,
20 | };
21 |
22 | const account3 = {
23 | owner: 'Steven Thomas Williams',
24 | movements: [200, -200, 340, -300, -20, 50, 400, -460],
25 | interestRate: 0.7,
26 | pin: 3333,
27 | };
28 |
29 | const account4 = {
30 | owner: 'Sarah Smith',
31 | movements: [430, 1000, 700, 50, 90],
32 | interestRate: 1,
33 | pin: 4444,
34 | };
35 |
36 | const accounts = [account1, account2, account3, account4];
37 |
38 | // Elements
39 | const labelWelcome = document.querySelector('.welcome');
40 | const labelDate = document.querySelector('.date');
41 | const labelBalance = document.querySelector('.balance__value');
42 | const labelSumIn = document.querySelector('.summary__value--in');
43 | const labelSumOut = document.querySelector('.summary__value--out');
44 | const labelSumInterest = document.querySelector('.summary__value--interest');
45 | const labelTimer = document.querySelector('.timer');
46 |
47 | const containerApp = document.querySelector('.app');
48 | const containerMovements = document.querySelector('.movements');
49 |
50 | const btnLogin = document.querySelector('.login__btn');
51 | const btnTransfer = document.querySelector('.form__btn--transfer');
52 | const btnLoan = document.querySelector('.form__btn--loan');
53 | const btnClose = document.querySelector('.form__btn--close');
54 | const btnSort = document.querySelector('.btn--sort');
55 |
56 | const inputLoginUsername = document.querySelector('.login__input--user');
57 | const inputLoginPin = document.querySelector('.login__input--pin');
58 | const inputTransferTo = document.querySelector('.form__input--to');
59 | const inputTransferAmount = document.querySelector('.form__input--amount');
60 | const inputLoanAmount = document.querySelector('.form__input--loan-amount');
61 | const inputCloseUsername = document.querySelector('.form__input--user');
62 | const inputClosePin = document.querySelector('.form__input--pin');
63 |
64 | /////////////////////////////////////////////////
65 | /////////////////////////////////////////////////
66 | // LECTURES
67 |
68 | const currencies = new Map([
69 | ['USD', 'United States dollar'],
70 | ['EUR', 'Euro'],
71 | ['GBP', 'Pound sterling'],
72 | ]);
73 |
74 | const movements = [200, 450, -400, 3000, -650, -130, 70, 1300];
75 |
76 | /////////////////////////////////////////////////
77 |
--------------------------------------------------------------------------------
/12-Numbers-Dates-Timers-Bankist/final/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/12-Numbers-Dates-Timers-Bankist/final/Bankist-flowchart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/12-Numbers-Dates-Timers-Bankist/final/Bankist-flowchart.png
--------------------------------------------------------------------------------
/12-Numbers-Dates-Timers-Bankist/final/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/12-Numbers-Dates-Timers-Bankist/final/icon.png
--------------------------------------------------------------------------------
/12-Numbers-Dates-Timers-Bankist/final/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
13 |
14 |
15 | Bankist
16 |
17 |
18 |
19 |
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 |
--------------------------------------------------------------------------------
/12-Numbers-Dates-Timers-Bankist/final/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/12-Numbers-Dates-Timers-Bankist/final/logo.png
--------------------------------------------------------------------------------
/12-Numbers-Dates-Timers-Bankist/starter/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/12-Numbers-Dates-Timers-Bankist/starter/Bankist-flowchart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/12-Numbers-Dates-Timers-Bankist/starter/Bankist-flowchart.png
--------------------------------------------------------------------------------
/12-Numbers-Dates-Timers-Bankist/starter/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/12-Numbers-Dates-Timers-Bankist/starter/icon.png
--------------------------------------------------------------------------------
/12-Numbers-Dates-Timers-Bankist/starter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
13 |
14 |
15 | Bankist
16 |
17 |
18 |
19 |
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 |
--------------------------------------------------------------------------------
/12-Numbers-Dates-Timers-Bankist/starter/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/12-Numbers-Dates-Timers-Bankist/starter/logo.png
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/final/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/final/img/card-lazy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/card-lazy.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/final/img/card.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/card.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/final/img/digital-lazy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/digital-lazy.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/final/img/digital.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/digital.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/final/img/grow-lazy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/grow-lazy.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/final/img/grow.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/grow.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/final/img/hero.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/hero.png
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/final/img/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/icon.png
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/final/img/img-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/img-1.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/final/img/img-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/img-2.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/final/img/img-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/img-3.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/final/img/img-4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/img-4.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/final/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/logo.png
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/final/img/user-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/user-1.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/final/img/user-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/user-2.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/final/img/user-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/final/img/user-3.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/starter/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/starter/img/card-lazy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/card-lazy.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/starter/img/card.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/card.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/starter/img/digital-lazy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/digital-lazy.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/starter/img/digital.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/digital.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/starter/img/grow-lazy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/grow-lazy.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/starter/img/grow.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/grow.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/starter/img/hero.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/hero.png
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/starter/img/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/icon.png
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/starter/img/img-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/img-1.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/starter/img/img-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/img-2.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/starter/img/img-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/img-3.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/starter/img/img-4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/img-4.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/starter/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/logo.png
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/starter/img/user-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/user-1.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/starter/img/user-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/user-2.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/starter/img/user-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/13-Advanced-DOM-Bankist/starter/img/user-3.jpg
--------------------------------------------------------------------------------
/13-Advanced-DOM-Bankist/starter/script.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | ///////////////////////////////////////
4 | // Modal window
5 |
6 | const modal = document.querySelector('.modal');
7 | const overlay = document.querySelector('.overlay');
8 | const btnCloseModal = document.querySelector('.btn--close-modal');
9 | const btnsOpenModal = document.querySelectorAll('.btn--show-modal');
10 |
11 | const openModal = function () {
12 | modal.classList.remove('hidden');
13 | overlay.classList.remove('hidden');
14 | };
15 |
16 | const closeModal = function () {
17 | modal.classList.add('hidden');
18 | overlay.classList.add('hidden');
19 | };
20 |
21 | for (let i = 0; i < btnsOpenModal.length; i++)
22 | btnsOpenModal[i].addEventListener('click', openModal);
23 |
24 | btnCloseModal.addEventListener('click', closeModal);
25 | overlay.addEventListener('click', closeModal);
26 |
27 | document.addEventListener('keydown', function (e) {
28 | if (e.key === 'Escape' && !modal.classList.contains('hidden')) {
29 | closeModal();
30 | }
31 | });
32 |
--------------------------------------------------------------------------------
/14-OOP/final/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/14-OOP/final/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Object Oriented Programming (OOP) With JavaScript
8 |
25 |
26 |
27 |
28 | Object Oriented Programming (OOP) With JavaScript
29 |
30 |
31 |
--------------------------------------------------------------------------------
/14-OOP/starter/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/14-OOP/starter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Object Oriented Programming (OOP) With JavaScript
8 |
25 |
26 |
27 |
28 | Object Oriented Programming (OOP) With JavaScript
29 |
30 |
31 |
--------------------------------------------------------------------------------
/14-OOP/starter/script.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
--------------------------------------------------------------------------------
/15-Mapty/final/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/15-Mapty/final/Mapty-architecture-final.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/15-Mapty/final/Mapty-architecture-final.png
--------------------------------------------------------------------------------
/15-Mapty/final/Mapty-architecture-part-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/15-Mapty/final/Mapty-architecture-part-1.png
--------------------------------------------------------------------------------
/15-Mapty/final/Mapty-flowchart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/15-Mapty/final/Mapty-flowchart.png
--------------------------------------------------------------------------------
/15-Mapty/final/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/15-Mapty/final/icon.png
--------------------------------------------------------------------------------
/15-Mapty/final/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/15-Mapty/final/logo.png
--------------------------------------------------------------------------------
/15-Mapty/final/other.js:
--------------------------------------------------------------------------------
1 | const firstName = 'Jonas';
2 | console.log(months);
3 |
--------------------------------------------------------------------------------
/15-Mapty/final/style.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --color-brand--1: #ffb545;
3 | --color-brand--2: #00c46a;
4 |
5 | --color-dark--1: #2d3439;
6 | --color-dark--2: #42484d;
7 | --color-light--1: #aaa;
8 | --color-light--2: #ececec;
9 | --color-light--3: rgb(214, 222, 224);
10 | }
11 |
12 | * {
13 | margin: 0;
14 | padding: 0;
15 | box-sizing: inherit;
16 | }
17 |
18 | html {
19 | font-size: 62.5%;
20 | box-sizing: border-box;
21 | }
22 |
23 | body {
24 | font-family: 'Manrope', sans-serif;
25 | color: var(--color-light--2);
26 | font-weight: 400;
27 | line-height: 1.6;
28 | height: 100vh;
29 | overscroll-behavior-y: none;
30 |
31 | background-color: #fff;
32 | padding: 2.5rem;
33 |
34 | display: flex;
35 | }
36 |
37 | /* GENERAL */
38 | a:link,
39 | a:visited {
40 | color: var(--color-brand--1);
41 | }
42 |
43 | /* SIDEBAR */
44 | .sidebar {
45 | flex-basis: 50rem;
46 | background-color: var(--color-dark--1);
47 | padding: 3rem 5rem 4rem 5rem;
48 | display: flex;
49 | flex-direction: column;
50 | }
51 |
52 | .logo {
53 | height: 5.2rem;
54 | align-self: center;
55 | margin-bottom: 4rem;
56 | }
57 |
58 | .workouts {
59 | list-style: none;
60 | height: 77vh;
61 | overflow-y: scroll;
62 | overflow-x: hidden;
63 | }
64 |
65 | .workouts::-webkit-scrollbar {
66 | width: 0;
67 | }
68 |
69 | .workout {
70 | background-color: var(--color-dark--2);
71 | border-radius: 5px;
72 | padding: 1.5rem 2.25rem;
73 | margin-bottom: 1.75rem;
74 | cursor: pointer;
75 |
76 | display: grid;
77 | grid-template-columns: 1fr 1fr 1fr 1fr;
78 | gap: 0.75rem 1.5rem;
79 | }
80 | .workout--running {
81 | border-left: 5px solid var(--color-brand--2);
82 | }
83 | .workout--cycling {
84 | border-left: 5px solid var(--color-brand--1);
85 | }
86 |
87 | .workout__title {
88 | font-size: 1.7rem;
89 | font-weight: 600;
90 | grid-column: 1 / -1;
91 | }
92 |
93 | .workout__details {
94 | display: flex;
95 | align-items: baseline;
96 | }
97 |
98 | .workout__icon {
99 | font-size: 1.8rem;
100 | margin-right: 0.2rem;
101 | height: 0.28rem;
102 | }
103 |
104 | .workout__value {
105 | font-size: 1.5rem;
106 | margin-right: 0.5rem;
107 | }
108 |
109 | .workout__unit {
110 | font-size: 1.1rem;
111 | color: var(--color-light--1);
112 | text-transform: uppercase;
113 | font-weight: 800;
114 | }
115 |
116 | .form {
117 | background-color: var(--color-dark--2);
118 | border-radius: 5px;
119 | padding: 1.5rem 2.75rem;
120 | margin-bottom: 1.75rem;
121 |
122 | display: grid;
123 | grid-template-columns: 1fr 1fr;
124 | gap: 0.5rem 2.5rem;
125 |
126 | /* Match height and activity boxes */
127 | height: 9.25rem;
128 | transition: all 0.5s, transform 1ms;
129 | }
130 |
131 | .form.hidden {
132 | transform: translateY(-30rem);
133 | height: 0;
134 | padding: 0 2.25rem;
135 | margin-bottom: 0;
136 | opacity: 0;
137 | }
138 |
139 | .form__row {
140 | display: flex;
141 | align-items: center;
142 | }
143 |
144 | .form__row--hidden {
145 | display: none;
146 | }
147 |
148 | .form__label {
149 | flex: 0 0 50%;
150 | font-size: 1.5rem;
151 | font-weight: 600;
152 | }
153 |
154 | .form__input {
155 | width: 100%;
156 | padding: 0.3rem 1.1rem;
157 | font-family: inherit;
158 | font-size: 1.4rem;
159 | border: none;
160 | border-radius: 3px;
161 | background-color: var(--color-light--3);
162 | transition: all 0.2s;
163 | }
164 |
165 | .form__input:focus {
166 | outline: none;
167 | background-color: #fff;
168 | }
169 |
170 | .form__btn {
171 | display: none;
172 | }
173 |
174 | .copyright {
175 | margin-top: auto;
176 | font-size: 1.3rem;
177 | text-align: center;
178 | color: var(--color-light--1);
179 | }
180 |
181 | .twitter-link:link,
182 | .twitter-link:visited {
183 | color: var(--color-light--1);
184 | transition: all 0.2s;
185 | }
186 |
187 | .twitter-link:hover,
188 | .twitter-link:active {
189 | color: var(--color-light--2);
190 | }
191 |
192 | /* MAP */
193 | #map {
194 | flex: 1;
195 | height: 100%;
196 | background-color: var(--color-light--1);
197 | }
198 |
199 | /* Popup width is defined in JS using options */
200 | .leaflet-popup .leaflet-popup-content-wrapper {
201 | background-color: var(--color-dark--1);
202 | color: var(--color-light--2);
203 | border-radius: 5px;
204 | padding-right: 0.6rem;
205 | }
206 |
207 | .leaflet-popup .leaflet-popup-content {
208 | font-size: 1.5rem;
209 | }
210 |
211 | .leaflet-popup .leaflet-popup-tip {
212 | background-color: var(--color-dark--1);
213 | }
214 |
215 | .running-popup .leaflet-popup-content-wrapper {
216 | border-left: 5px solid var(--color-brand--2);
217 | }
218 | .cycling-popup .leaflet-popup-content-wrapper {
219 | border-left: 5px solid var(--color-brand--1);
220 | }
221 |
--------------------------------------------------------------------------------
/15-Mapty/starter/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/15-Mapty/starter/Mapty-architecture-final.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/15-Mapty/starter/Mapty-architecture-final.png
--------------------------------------------------------------------------------
/15-Mapty/starter/Mapty-architecture-part-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/15-Mapty/starter/Mapty-architecture-part-1.png
--------------------------------------------------------------------------------
/15-Mapty/starter/Mapty-flowchart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/15-Mapty/starter/Mapty-flowchart.png
--------------------------------------------------------------------------------
/15-Mapty/starter/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/15-Mapty/starter/icon.png
--------------------------------------------------------------------------------
/15-Mapty/starter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
13 |
14 |
15 |
16 |
17 | mapty // Map your workouts
18 |
19 |
20 |
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/15-Mapty/starter/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/15-Mapty/starter/logo.png
--------------------------------------------------------------------------------
/15-Mapty/starter/script.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // prettier-ignore
4 | const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
5 |
6 | const form = document.querySelector('.form');
7 | const containerWorkouts = document.querySelector('.workouts');
8 | const inputType = document.querySelector('.form__input--type');
9 | const inputDistance = document.querySelector('.form__input--distance');
10 | const inputDuration = document.querySelector('.form__input--duration');
11 | const inputCadence = document.querySelector('.form__input--cadence');
12 | const inputElevation = document.querySelector('.form__input--elevation');
13 |
--------------------------------------------------------------------------------
/15-Mapty/starter/style.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --color-brand--1: #ffb545;
3 | --color-brand--2: #00c46a;
4 |
5 | --color-dark--1: #2d3439;
6 | --color-dark--2: #42484d;
7 | --color-light--1: #aaa;
8 | --color-light--2: #ececec;
9 | --color-light--3: rgb(214, 222, 224);
10 | }
11 |
12 | * {
13 | margin: 0;
14 | padding: 0;
15 | box-sizing: inherit;
16 | }
17 |
18 | html {
19 | font-size: 62.5%;
20 | box-sizing: border-box;
21 | }
22 |
23 | body {
24 | font-family: 'Manrope', sans-serif;
25 | color: var(--color-light--2);
26 | font-weight: 400;
27 | line-height: 1.6;
28 | height: 100vh;
29 | overscroll-behavior-y: none;
30 |
31 | background-color: #fff;
32 | padding: 2.5rem;
33 |
34 | display: flex;
35 | }
36 |
37 | /* GENERAL */
38 | a:link,
39 | a:visited {
40 | color: var(--color-brand--1);
41 | }
42 |
43 | /* SIDEBAR */
44 | .sidebar {
45 | flex-basis: 50rem;
46 | background-color: var(--color-dark--1);
47 | padding: 3rem 5rem 4rem 5rem;
48 | display: flex;
49 | flex-direction: column;
50 | }
51 |
52 | .logo {
53 | height: 5.2rem;
54 | align-self: center;
55 | margin-bottom: 4rem;
56 | }
57 |
58 | .workouts {
59 | list-style: none;
60 | height: 77vh;
61 | overflow-y: scroll;
62 | overflow-x: hidden;
63 | }
64 |
65 | .workouts::-webkit-scrollbar {
66 | width: 0;
67 | }
68 |
69 | .workout {
70 | background-color: var(--color-dark--2);
71 | border-radius: 5px;
72 | padding: 1.5rem 2.25rem;
73 | margin-bottom: 1.75rem;
74 | cursor: pointer;
75 |
76 | display: grid;
77 | grid-template-columns: 1fr 1fr 1fr 1fr;
78 | gap: 0.75rem 1.5rem;
79 | }
80 | .workout--running {
81 | border-left: 5px solid var(--color-brand--2);
82 | }
83 | .workout--cycling {
84 | border-left: 5px solid var(--color-brand--1);
85 | }
86 |
87 | .workout__title {
88 | font-size: 1.7rem;
89 | font-weight: 600;
90 | grid-column: 1 / -1;
91 | }
92 |
93 | .workout__details {
94 | display: flex;
95 | align-items: baseline;
96 | }
97 |
98 | .workout__icon {
99 | font-size: 1.8rem;
100 | margin-right: 0.2rem;
101 | height: 0.28rem;
102 | }
103 |
104 | .workout__value {
105 | font-size: 1.5rem;
106 | margin-right: 0.5rem;
107 | }
108 |
109 | .workout__unit {
110 | font-size: 1.1rem;
111 | color: var(--color-light--1);
112 | text-transform: uppercase;
113 | font-weight: 800;
114 | }
115 |
116 | .form {
117 | background-color: var(--color-dark--2);
118 | border-radius: 5px;
119 | padding: 1.5rem 2.75rem;
120 | margin-bottom: 1.75rem;
121 |
122 | display: grid;
123 | grid-template-columns: 1fr 1fr;
124 | gap: 0.5rem 2.5rem;
125 |
126 | /* Match height and activity boxes */
127 | height: 9.25rem;
128 | transition: all 0.5s, transform 1ms;
129 | }
130 |
131 | .form.hidden {
132 | transform: translateY(-30rem);
133 | height: 0;
134 | padding: 0 2.25rem;
135 | margin-bottom: 0;
136 | opacity: 0;
137 | }
138 |
139 | .form__row {
140 | display: flex;
141 | align-items: center;
142 | }
143 |
144 | .form__row--hidden {
145 | display: none;
146 | }
147 |
148 | .form__label {
149 | flex: 0 0 50%;
150 | font-size: 1.5rem;
151 | font-weight: 600;
152 | }
153 |
154 | .form__input {
155 | width: 100%;
156 | padding: 0.3rem 1.1rem;
157 | font-family: inherit;
158 | font-size: 1.4rem;
159 | border: none;
160 | border-radius: 3px;
161 | background-color: var(--color-light--3);
162 | transition: all 0.2s;
163 | }
164 |
165 | .form__input:focus {
166 | outline: none;
167 | background-color: #fff;
168 | }
169 |
170 | .form__btn {
171 | display: none;
172 | }
173 |
174 | .copyright {
175 | margin-top: auto;
176 | font-size: 1.3rem;
177 | text-align: center;
178 | color: var(--color-light--1);
179 | }
180 |
181 | .twitter-link:link,
182 | .twitter-link:visited {
183 | color: var(--color-light--1);
184 | transition: all 0.2s;
185 | }
186 |
187 | .twitter-link:hover,
188 | .twitter-link:active {
189 | color: var(--color-light--2);
190 | }
191 |
192 | /* MAP */
193 | #map {
194 | flex: 1;
195 | height: 100%;
196 | background-color: var(--color-light--1);
197 | }
198 |
199 | /* Popup width is defined in JS using options */
200 | .leaflet-popup .leaflet-popup-content-wrapper {
201 | background-color: var(--color-dark--1);
202 | color: var(--color-light--2);
203 | border-radius: 5px;
204 | padding-right: 0.6rem;
205 | }
206 |
207 | .leaflet-popup .leaflet-popup-content {
208 | font-size: 1.5rem;
209 | }
210 |
211 | .leaflet-popup .leaflet-popup-tip {
212 | background-color: var(--color-dark--1);
213 | }
214 |
215 | .running-popup .leaflet-popup-content-wrapper {
216 | border-left: 5px solid var(--color-brand--2);
217 | }
218 | .cycling-popup .leaflet-popup-content-wrapper {
219 | border-left: 5px solid var(--color-brand--1);
220 | }
221 |
--------------------------------------------------------------------------------
/16-Asynchronous/final/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/16-Asynchronous/final/img/img-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/16-Asynchronous/final/img/img-1.jpg
--------------------------------------------------------------------------------
/16-Asynchronous/final/img/img-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/16-Asynchronous/final/img/img-2.jpg
--------------------------------------------------------------------------------
/16-Asynchronous/final/img/img-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/16-Asynchronous/final/img/img-3.jpg
--------------------------------------------------------------------------------
/16-Asynchronous/final/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Asynchronous JavaScript
10 |
11 |
12 |
13 |
14 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/16-Asynchronous/final/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | box-sizing: inherit;
5 | }
6 |
7 | html {
8 | font-size: 62.5%;
9 | box-sizing: border-box;
10 | }
11 |
12 | body {
13 | font-family: system-ui;
14 | color: #555;
15 | background-color: #f7f7f7;
16 | min-height: 100vh;
17 |
18 | display: flex;
19 | align-items: center;
20 | justify-content: center;
21 | }
22 |
23 | .container {
24 | display: flex;
25 | flex-flow: column;
26 | align-items: center;
27 | }
28 |
29 | .countries {
30 | /* margin-bottom: 8rem; */
31 | display: flex;
32 |
33 | font-size: 2rem;
34 | opacity: 0;
35 | transition: opacity 1s;
36 | }
37 |
38 | .country {
39 | background-color: #fff;
40 | box-shadow: 0 2rem 5rem 1rem rgba(0, 0, 0, 0.1);
41 | font-size: 1.8rem;
42 | width: 30rem;
43 | border-radius: 0.7rem;
44 | margin: 0 3rem;
45 | /* overflow: hidden; */
46 | }
47 |
48 | .neighbour::before {
49 | content: 'Neighbour country';
50 | width: 100%;
51 | position: absolute;
52 | top: -4rem;
53 |
54 | text-align: center;
55 | font-size: 1.8rem;
56 | font-weight: 600;
57 | text-transform: uppercase;
58 | color: #888;
59 | }
60 |
61 | .neighbour {
62 | transform: scale(0.8) translateY(1rem);
63 | margin-left: 0;
64 | }
65 |
66 | .country__img {
67 | width: 30rem;
68 | height: 17rem;
69 | object-fit: cover;
70 | background-color: #eee;
71 | border-top-left-radius: 0.7rem;
72 | border-top-right-radius: 0.7rem;
73 | }
74 |
75 | .country__data {
76 | padding: 2.5rem 3.75rem 3rem 3.75rem;
77 | }
78 |
79 | .country__name {
80 | font-size: 2.7rem;
81 | margin-bottom: 0.7rem;
82 | }
83 |
84 | .country__region {
85 | font-size: 1.4rem;
86 | margin-bottom: 2.5rem;
87 | text-transform: uppercase;
88 | color: #888;
89 | }
90 |
91 | .country__row:not(:last-child) {
92 | margin-bottom: 1rem;
93 | }
94 |
95 | .country__row span {
96 | display: inline-block;
97 | margin-right: 2rem;
98 | font-size: 2.4rem;
99 | }
100 |
101 | .btn-country {
102 | border: none;
103 | font-size: 2rem;
104 | padding: 2rem 5rem;
105 | border-radius: 0.7rem;
106 | color: white;
107 | background-color: orangered;
108 | cursor: pointer;
109 | }
110 |
111 | .images {
112 | display: flex;
113 | }
114 |
115 | .images img {
116 | display: block;
117 | width: 80rem;
118 | margin: 4rem;
119 | }
120 |
121 | .images img.parallel {
122 | width: 40rem;
123 | margin: 2rem;
124 | border: 3rem solid white;
125 | box-shadow: 0 2rem 5rem 1rem rgba(0, 0, 0, 0.1);
126 | }
127 |
--------------------------------------------------------------------------------
/16-Asynchronous/starter/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/16-Asynchronous/starter/img/img-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/16-Asynchronous/starter/img/img-1.jpg
--------------------------------------------------------------------------------
/16-Asynchronous/starter/img/img-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/16-Asynchronous/starter/img/img-2.jpg
--------------------------------------------------------------------------------
/16-Asynchronous/starter/img/img-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/16-Asynchronous/starter/img/img-3.jpg
--------------------------------------------------------------------------------
/16-Asynchronous/starter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Asynchronous JavaScript
10 |
11 |
12 |
13 |
14 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/16-Asynchronous/starter/script.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const btn = document.querySelector('.btn-country');
4 | const countriesContainer = document.querySelector('.countries');
5 |
6 | ///////////////////////////////////////
7 |
--------------------------------------------------------------------------------
/16-Asynchronous/starter/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | box-sizing: inherit;
5 | }
6 |
7 | html {
8 | font-size: 62.5%;
9 | box-sizing: border-box;
10 | }
11 |
12 | body {
13 | font-family: system-ui;
14 | color: #555;
15 | background-color: #f7f7f7;
16 | min-height: 100vh;
17 |
18 | display: flex;
19 | align-items: center;
20 | justify-content: center;
21 | }
22 |
23 | .container {
24 | display: flex;
25 | flex-flow: column;
26 | align-items: center;
27 | }
28 |
29 | .countries {
30 | /* margin-bottom: 8rem; */
31 | display: flex;
32 |
33 | font-size: 2rem;
34 | opacity: 0;
35 | transition: opacity 1s;
36 | }
37 |
38 | .country {
39 | background-color: #fff;
40 | box-shadow: 0 2rem 5rem 1rem rgba(0, 0, 0, 0.1);
41 | font-size: 1.8rem;
42 | width: 30rem;
43 | border-radius: 0.7rem;
44 | margin: 0 3rem;
45 | /* overflow: hidden; */
46 | }
47 |
48 | .neighbour::before {
49 | content: 'Neighbour country';
50 | width: 100%;
51 | position: absolute;
52 | top: -4rem;
53 |
54 | text-align: center;
55 | font-size: 1.8rem;
56 | font-weight: 600;
57 | text-transform: uppercase;
58 | color: #888;
59 | }
60 |
61 | .neighbour {
62 | transform: scale(0.8) translateY(1rem);
63 | margin-left: 0;
64 | }
65 |
66 | .country__img {
67 | width: 30rem;
68 | height: 17rem;
69 | object-fit: cover;
70 | background-color: #eee;
71 | border-top-left-radius: 0.7rem;
72 | border-top-right-radius: 0.7rem;
73 | }
74 |
75 | .country__data {
76 | padding: 2.5rem 3.75rem 3rem 3.75rem;
77 | }
78 |
79 | .country__name {
80 | font-size: 2.7rem;
81 | margin-bottom: 0.7rem;
82 | }
83 |
84 | .country__region {
85 | font-size: 1.4rem;
86 | margin-bottom: 2.5rem;
87 | text-transform: uppercase;
88 | color: #888;
89 | }
90 |
91 | .country__row:not(:last-child) {
92 | margin-bottom: 1rem;
93 | }
94 |
95 | .country__row span {
96 | display: inline-block;
97 | margin-right: 2rem;
98 | font-size: 2.4rem;
99 | }
100 |
101 | .btn-country {
102 | border: none;
103 | font-size: 2rem;
104 | padding: 2rem 5rem;
105 | border-radius: 0.7rem;
106 | color: white;
107 | background-color: orangered;
108 | cursor: pointer;
109 | }
110 |
111 | .images {
112 | display: flex;
113 | }
114 |
115 | .images img {
116 | display: block;
117 | width: 80rem;
118 | margin: 4rem;
119 | }
120 |
121 | .images img.parallel {
122 | width: 40rem;
123 | margin: 2rem;
124 | border: 3rem solid white;
125 | box-shadow: 0 2rem 5rem 1rem rgba(0, 0, 0, 0.1);
126 | }
127 |
--------------------------------------------------------------------------------
/17-Modern-JS-Modules-Tooling/final/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/17-Modern-JS-Modules-Tooling/final/clean.js:
--------------------------------------------------------------------------------
1 | 'strict mode';
2 |
3 | const budget = Object.freeze([
4 | { value: 250, description: 'Sold old TV 📺', user: 'jonas' },
5 | { value: -45, description: 'Groceries 🥑', user: 'jonas' },
6 | { value: 3500, description: 'Monthly salary 👩💻', user: 'jonas' },
7 | { value: 300, description: 'Freelancing 👩💻', user: 'jonas' },
8 | { value: -1100, description: 'New iPhone 📱', user: 'jonas' },
9 | { value: -20, description: 'Candy 🍭', user: 'matilda' },
10 | { value: -125, description: 'Toys 🚂', user: 'matilda' },
11 | { value: -1800, description: 'New Laptop 💻', user: 'jonas' },
12 | ]);
13 |
14 | const spendingLimits = Object.freeze({
15 | jonas: 1500,
16 | matilda: 100,
17 | });
18 | // spendingLimits.jay = 200;
19 |
20 | // const limit = spendingLimits[user] ? spendingLimits[user] : 0;
21 | const getLimit = (limits, user) => limits?.[user] ?? 0;
22 |
23 | // Pure function :D
24 | const addExpense = function (
25 | state,
26 | limits,
27 | value,
28 | description,
29 | user = 'jonas'
30 | ) {
31 | const cleanUser = user.toLowerCase();
32 |
33 | return value <= getLimit(limits, cleanUser)
34 | ? [...state, { value: -value, description, user: cleanUser }]
35 | : state;
36 | };
37 |
38 | const newBudget1 = addExpense(budget, spendingLimits, 10, 'Pizza 🍕');
39 | const newBudget2 = addExpense(
40 | newBudget1,
41 | spendingLimits,
42 | 100,
43 | 'Going to movies 🍿',
44 | 'Matilda'
45 | );
46 | const newBudget3 = addExpense(newBudget2, spendingLimits, 200, 'Stuff', 'Jay');
47 |
48 | // const checkExpenses2 = function (state, limits) {
49 | // return state.map(entry => {
50 | // return entry.value < -getLimit(limits, entry.user)
51 | // ? { ...entry, flag: 'limit' }
52 | // : entry;
53 | // });
54 | // // for (const entry of newBudget3)
55 | // // if (entry.value < -getLimit(limits, entry.user)) entry.flag = 'limit';
56 | // };
57 |
58 | const checkExpenses = (state, limits) =>
59 | state.map(entry =>
60 | entry.value < -getLimit(limits, entry.user)
61 | ? { ...entry, flag: 'limit' }
62 | : entry
63 | );
64 |
65 | const finalBudget = checkExpenses(newBudget3, spendingLimits);
66 | console.log(finalBudget);
67 |
68 | // Impure
69 | const logBigExpenses = function (state, bigLimit) {
70 | const bigExpenses = state
71 | .filter(entry => entry.value <= -bigLimit)
72 | .map(entry => entry.description.slice(-2))
73 | .join(' / ');
74 | // .reduce((str, cur) => `${str} / ${cur.description.slice(-2)}`, '');
75 |
76 | console.log(bigExpenses);
77 |
78 | // let output = '';
79 | // for (const entry of budget)
80 | // output +=
81 | // entry.value <= -bigLimit ? `${entry.description.slice(-2)} / ` : '';
82 | // output = output.slice(0, -2); // Remove last '/ '
83 | // console.log(output);
84 | };
85 |
86 | logBigExpenses(finalBudget, 500);
87 |
--------------------------------------------------------------------------------
/17-Modern-JS-Modules-Tooling/final/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Modern JavaScript Development: Modules and Tooling
11 |
26 |
27 |
28 | Modern JavaScript Development: Modules and Tooling
29 |
30 |
31 |
--------------------------------------------------------------------------------
/17-Modern-JS-Modules-Tooling/final/dist/index.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["node_modules/parcel/src/builtins/bundle-url.js","node_modules/parcel/src/builtins/css-loader.js"],"names":["bundleURL","getBundleURLCached","getBundleURL","Error","err","matches","stack","match","getBaseURL","url","replace","exports","bundle","require","updateLink","link","newLink","cloneNode","onload","remove","href","split","Date","now","parentNode","insertBefore","nextSibling","cssTimeout","reloadCSS","setTimeout","links","document","querySelectorAll","i","length","module"],"mappings":"AAAA,ACAA,IDAIA,ACAAY,MAAM,GDAG,ACAAC,GDAG,IAAhB,ACAoB,CAAC,cAAD,CAApB;;ADCA,ACCA,SDDSZ,ACCAa,UAAT,CAAoBC,IAApB,EAA0B,CDD1B,GAA8B;AAC5B,ACCA,MDDI,ACCAC,CDDChB,MCCM,GDDX,ACCce,EDDE,ECCE,CAACE,SAAL,EAAd;ADAEjB,IAAAA,SAAS,GAAGE,YAAY,EAAxB;AACD,ACADc,EAAAA,OAAO,CAACE,MAAR,GAAiB,YAAY;AAC3BH,IAAAA,IAAI,CAACI,MAAL;ADCF,ACAC,GAFD,MDEOnB,SAAP;AACD;ACACgB,EAAAA,OAAO,CAACI,IAAR,GAAeL,IAAI,CAACK,IAAL,CAAUC,KAAV,CAAgB,GAAhB,EAAqB,CAArB,IAA0B,GAA1B,GAAgCC,IAAI,CAACC,GAAL,EAA/C;ADEF,ACDER,EAAAA,IAAI,CAACS,EDCEtB,QCDP,CAAgBuB,GDClB,GAAwB,MCDtB,CAA6BT,OAA7B,EAAsCD,IAAI,CAACW,WAA3C;ADEA,ACDD;ADEC,MAAI;AACF,ACDJ,IAAIC,MDCM,IAAIxB,ACDA,GAAG,EDCP,EAAN,ACDJ;ADEG,GAFD,CAEE,OAAOC,GAAP,EAAY;AACZ,ACFJ,QDEQC,CCFCuB,MDEM,GAAG,ACFlB,CDEmB,ECFE,GDEGxB,GAAG,CAACE,KAAV,EAAiBC,KAAjB,CAAuB,+DAAvB,CAAd;ACDF,MAAIoB,UAAJ,EAAgB;ADEd,ACDA,QDCItB,OAAJ,EAAa;AACX,ACDH,aDCUG,UAAU,CAACH,OAAO,CAAC,CAAD,CAAR,CAAjB;AACD;AACF,ACDDsB,EAAAA,UAAU,GAAGE,UAAU,CAAC,YAAY;AAClC,QAAIC,KAAK,GAAGC,QAAQ,CAACC,gBAAT,CAA0B,wBAA1B,CAAZ;ADEF,SAAO,GAAP;AACD,ACFG,SAAK,IAAIC,CAAC,GAAG,CAAb,EAAgBA,CAAC,GAAGH,KAAK,CAACI,MAA1B,EAAkCD,CAAC,EAAnC,EAAuC;AACrC,UAAIrB,MAAM,CAACJ,UAAP,CAAkBsB,KAAK,CAACG,CAAD,CAAL,CAASb,IAA3B,MAAqCR,MAAM,CAACV,YAAP,EAAzC,EAAgE;ADGtE,ACFQY,QAAAA,CDECN,SCFS,CDElB,ACFmBsB,CDECrB,GAApB,CCFwB,CDEC,ACFAwB,CAAD,CAAN,CAAV;ADGN,ACFK,SDEE,CAAC,KAAKxB,GAAN,EAAWC,OAAX,CAAmB,sEAAnB,EAA2F,IAA3F,IAAmG,GAA1G;AACD,ACFI;;ADILC,ACFIgB,IAAAA,GDEG,CAACzB,MCFM,GAAG,GDEjB,CCFI,EDEmBD,kBAAvB;AACAU,ACFG,GATsB,EASpB,EDEE,ACXkB,CDWjBH,ACXN,UDWF,GAAqBA,UAArB;ACDC;;AAED2B,MAAM,CAACxB,OAAP,GAAiBiB,SAAjB","file":"index.js","sourceRoot":"..","sourcesContent":["var bundleURL = null;\nfunction getBundleURLCached() {\n if (!bundleURL) {\n bundleURL = getBundleURL();\n }\n\n return bundleURL;\n}\n\nfunction getBundleURL() {\n // Attempt to find the URL of the current script and use that as the base URL\n try {\n throw new Error;\n } catch (err) {\n var matches = ('' + err.stack).match(/(https?|file|ftp|chrome-extension|moz-extension):\\/\\/[^)\\n]+/g);\n if (matches) {\n return getBaseURL(matches[0]);\n }\n }\n\n return '/';\n}\n\nfunction getBaseURL(url) {\n return ('' + url).replace(/^((?:https?|file|ftp|chrome-extension|moz-extension):\\/\\/.+)\\/[^/]+$/, '$1') + '/';\n}\n\nexports.getBundleURL = getBundleURLCached;\nexports.getBaseURL = getBaseURL;\n","var bundle = require('./bundle-url');\n\nfunction updateLink(link) {\n var newLink = link.cloneNode();\n newLink.onload = function () {\n link.remove();\n };\n newLink.href = link.href.split('?')[0] + '?' + Date.now();\n link.parentNode.insertBefore(newLink, link.nextSibling);\n}\n\nvar cssTimeout = null;\nfunction reloadCSS() {\n if (cssTimeout) {\n return;\n }\n\n cssTimeout = setTimeout(function () {\n var links = document.querySelectorAll('link[rel=\"stylesheet\"]');\n for (var i = 0; i < links.length; i++) {\n if (bundle.getBaseURL(links[i].href) === bundle.getBundleURL()) {\n updateLink(links[i]);\n }\n }\n\n cssTimeout = null;\n }, 50);\n}\n\nmodule.exports = reloadCSS;\n"]}
--------------------------------------------------------------------------------
/17-Modern-JS-Modules-Tooling/final/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Modern JavaScript Development: Modules and Tooling
12 |
29 |
30 |
31 | Modern JavaScript Development: Modules and Tooling
32 |
33 |
34 |
--------------------------------------------------------------------------------
/17-Modern-JS-Modules-Tooling/final/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "17-modern-js-modules-tooling",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "script.js",
6 | "scripts": {
7 | "start": "parcel index.html",
8 | "build": "parcel build index.html"
9 | },
10 | "author": "Jonas",
11 | "license": "ISC",
12 | "dependencies": {
13 | "core-js": "^3.6.5",
14 | "leaflet": "^1.6.0",
15 | "lodash-es": "^4.17.15",
16 | "regenerator-runtime": "^0.13.7"
17 | },
18 | "devDependencies": {
19 | "parcel": "^1.12.4"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/17-Modern-JS-Modules-Tooling/final/script.js:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////
2 | // Exporting and Importing in ES6 Modules
3 |
4 | // Importing module
5 | // import { addToCart, totalPrice as price, tq } from './shoppingCart.js';
6 | // addToCart('bread', 5);
7 | // console.log(price, tq);
8 |
9 | console.log('Importing module');
10 | // console.log(shippingCost);
11 |
12 | // import * as ShoppingCart from './shoppingCart.js';
13 | // ShoppingCart.addToCart('bread', 5);
14 | // console.log(ShoppingCart.totalPrice);
15 |
16 | // import add, { addToCart, totalPrice as price, tq } from './shoppingCart.js';
17 | // console.log(price);
18 |
19 | import add, { cart } from './shoppingCart.js';
20 | add('pizza', 2);
21 | add('bread', 5);
22 | add('apples', 4);
23 |
24 | console.log(cart);
25 | /*
26 |
27 |
28 | ///////////////////////////////////////
29 | // Top-Level Await (ES2022)
30 |
31 | // console.log('Start fetching');
32 | // const res = await fetch('https://jsonplaceholder.typicode.com/posts');
33 | // const data = await res.json();
34 | // console.log(data);
35 | // console.log('Something');
36 |
37 | const getLastPost = async function () {
38 | const res = await fetch('https://jsonplaceholder.typicode.com/posts');
39 | const data = await res.json();
40 |
41 | return { title: data.at(-1).title, text: data.at(-1).body };
42 | };
43 |
44 | const lastPost = getLastPost();
45 | console.log(lastPost);
46 |
47 | // Not very clean
48 | // lastPost.then(last => console.log(last));
49 |
50 | const lastPost2 = await getLastPost();
51 | console.log(lastPost2);
52 |
53 |
54 | ///////////////////////////////////////
55 | // The Module Pattern
56 |
57 | const ShoppingCart2 = (function () {
58 | const cart = [];
59 | const shippingCost = 10;
60 | const totalPrice = 237;
61 | const totalQuantity = 23;
62 |
63 | const addToCart = function (product, quantity) {
64 | cart.push({ product, quantity });
65 | console.log(
66 | `${quantity} ${product} added to cart (sipping cost is ${shippingCost})`
67 | );
68 | };
69 |
70 | const orderStock = function (product, quantity) {
71 | console.log(`${quantity} ${product} ordered from supplier`);
72 | };
73 |
74 | return {
75 | addToCart,
76 | cart,
77 | totalPrice,
78 | totalQuantity,
79 | };
80 | })();
81 |
82 | ShoppingCart2.addToCart('apple', 4);
83 | ShoppingCart2.addToCart('pizza', 2);
84 | console.log(ShoppingCart2);
85 | console.log(ShoppingCart2.shippingCost);
86 |
87 |
88 | ///////////////////////////////////////
89 | // CommonJS Modules
90 | // Export
91 | export.addTocart = function (product, quantity) {
92 | cart.push({ product, quantity });
93 | console.log(
94 | `${quantity} ${product} added to cart (sipping cost is ${shippingCost})`
95 | );
96 | };
97 |
98 | // Import
99 | const { addTocart } = require('./shoppingCart.js');
100 | */
101 |
102 | ///////////////////////////////////////
103 | // Introduction to NPM
104 | // import cloneDeep from './node_modules/lodash-es/cloneDeep.js';
105 | import cloneDeep from 'lodash-es';
106 |
107 | const state = {
108 | cart: [
109 | { product: 'bread', quantity: 5 },
110 | { product: 'pizza', quantity: 5 },
111 | ],
112 | user: { loggedIn: true },
113 | };
114 | const stateClone = Object.assign({}, state);
115 | const stateDeepClone = cloneDeep(state);
116 |
117 | state.user.loggedIn = false;
118 | console.log(stateClone);
119 |
120 | console.log(stateDeepClone);
121 |
122 | if (module.hot) {
123 | module.hot.accept();
124 | }
125 |
126 | class Person {
127 | #greeting = 'Hey';
128 | constructor(name) {
129 | this.name = name;
130 | console.log(`${this.#greeting}, ${this.name}`);
131 | }
132 | }
133 | const jonas = new Person('Jonas');
134 |
135 | console.log('Jonas' ?? null);
136 |
137 | console.log(cart.find(el => el.quantity >= 2));
138 | Promise.resolve('TEST').then(x => console.log(x));
139 |
140 | import 'core-js/stable';
141 | // import 'core-js/stable/array/find';
142 | // import 'core-js/stable/promise';
143 |
144 | // Polifilling async functions
145 | import 'regenerator-runtime/runtime';
146 |
--------------------------------------------------------------------------------
/17-Modern-JS-Modules-Tooling/final/shoppingCart.js:
--------------------------------------------------------------------------------
1 | // Exporting module
2 | console.log('Exporting module');
3 |
4 | // Blocking code
5 | // console.log('Start fetching users');
6 | // await fetch('https://jsonplaceholder.typicode.com/users');
7 | // console.log('Finish fetching users');
8 |
9 | const shippingCost = 10;
10 | export const cart = [];
11 |
12 | export const addToCart = function (product, quantity) {
13 | cart.push({ product, quantity });
14 | console.log(`${quantity} ${product} added to cart`);
15 | };
16 |
17 | const totalPrice = 237;
18 | const totalQuantity = 23;
19 |
20 | export { totalPrice, totalQuantity as tq };
21 |
22 | export default function (product, quantity) {
23 | cart.push({ product, quantity });
24 | console.log(`${quantity} ${product} added to cart`);
25 | }
26 |
--------------------------------------------------------------------------------
/17-Modern-JS-Modules-Tooling/starter/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/17-Modern-JS-Modules-Tooling/starter/clean.js:
--------------------------------------------------------------------------------
1 | var budget = [
2 | { value: 250, description: 'Sold old TV 📺', user: 'jonas' },
3 | { value: -45, description: 'Groceries 🥑', user: 'jonas' },
4 | { value: 3500, description: 'Monthly salary 👩💻', user: 'jonas' },
5 | { value: 300, description: 'Freelancing 👩💻', user: 'jonas' },
6 | { value: -1100, description: 'New iPhone 📱', user: 'jonas' },
7 | { value: -20, description: 'Candy 🍭', user: 'matilda' },
8 | { value: -125, description: 'Toys 🚂', user: 'matilda' },
9 | { value: -1800, description: 'New Laptop 💻', user: 'jonas' },
10 | ];
11 |
12 | var limits = {
13 | jonas: 1500,
14 | matilda: 100,
15 | };
16 |
17 | var add = function (value, description, user) {
18 | if (!user) user = 'jonas';
19 | user = user.toLowerCase();
20 |
21 | var lim;
22 | if (limits[user]) {
23 | lim = limits[user];
24 | } else {
25 | lim = 0;
26 | }
27 |
28 | if (value <= lim) {
29 | budget.push({ value: -value, description: description, user: user });
30 | }
31 | };
32 | add(10, 'Pizza 🍕');
33 | add(100, 'Going to movies 🍿', 'Matilda');
34 | add(200, 'Stuff', 'Jay');
35 | console.log(budget);
36 |
37 | var check = function () {
38 | for (var el of budget) {
39 | var lim;
40 | if (limits[el.user]) {
41 | lim = limits[el.user];
42 | } else {
43 | lim = 0;
44 | }
45 |
46 | if (el.value < -lim) {
47 | el.flag = 'limit';
48 | }
49 | }
50 | };
51 | check();
52 |
53 | console.log(budget);
54 |
55 | var bigExpenses = function (limit) {
56 | var output = '';
57 | for (var el of budget) {
58 | if (el.value <= -limit) {
59 | output += el.description.slice(-2) + ' / '; // Emojis are 2 chars
60 | }
61 | }
62 | output = output.slice(0, -2); // Remove last '/ '
63 | console.log(output);
64 | };
65 |
--------------------------------------------------------------------------------
/17-Modern-JS-Modules-Tooling/starter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Modern JavaScript Development: Modules and Tooling
9 |
26 |
27 |
28 | Modern JavaScript Development: Modules and Tooling
29 |
30 |
31 |
--------------------------------------------------------------------------------
/17-Modern-JS-Modules-Tooling/starter/script.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/17-Modern-JS-Modules-Tooling/starter/script.js
--------------------------------------------------------------------------------
/18-forkify/final/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | .parcel-cache
4 | .DS_Store
5 |
--------------------------------------------------------------------------------
/18-forkify/final/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/18-forkify/final/README.md:
--------------------------------------------------------------------------------
1 | # forkify Project
2 |
3 | Recipe application with custom recipe uploads.
4 |
--------------------------------------------------------------------------------
/18-forkify/final/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "forkify",
3 | "version": "1.0.0",
4 | "description": "Recipe application",
5 | "default": "index.html",
6 | "scripts": {
7 | "start": "parcel index.html",
8 | "build": "parcel build index.html --dist-dir ./dist"
9 | },
10 | "author": "Jonas Schedtmann",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "parcel": "^2.0.0-beta.1",
14 | "sass": "^1.26.10"
15 | },
16 | "dependencies": {
17 | "core-js": "^3.6.5",
18 | "fractional": "^1.0.0",
19 | "regenerator-runtime": "^0.13.7"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/18-forkify/final/src/img/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/18-forkify/final/src/img/favicon.png
--------------------------------------------------------------------------------
/18-forkify/final/src/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/18-forkify/final/src/img/logo.png
--------------------------------------------------------------------------------
/18-forkify/final/src/js/config.js:
--------------------------------------------------------------------------------
1 | export const API_URL = 'https://forkify-api.herokuapp.com/api/v2/recipes/';
2 | export const TIMEOUT_SEC = 10;
3 | export const RES_PER_PAGE = 10;
4 | export const KEY = '';
5 | export const MODAL_CLOSE_SEC = 2.5;
6 |
--------------------------------------------------------------------------------
/18-forkify/final/src/js/controller.js:
--------------------------------------------------------------------------------
1 | import * as model from './model.js';
2 | import { MODAL_CLOSE_SEC } from './config.js';
3 | import recipeView from './views/recipeView.js';
4 | import searchView from './views/searchView.js';
5 | import resultsView from './views/resultsView.js';
6 | import paginationView from './views/paginationView.js';
7 | import bookmarksView from './views/bookmarksView.js';
8 | import addRecipeView from './views/addRecipeView.js';
9 |
10 | import 'core-js/stable';
11 | import 'regenerator-runtime/runtime';
12 | import { async } from 'regenerator-runtime';
13 |
14 | const controlRecipes = async function () {
15 | try {
16 | const id = window.location.hash.slice(1);
17 |
18 | if (!id) return;
19 | recipeView.renderSpinner();
20 |
21 | // 0) Update results view to mark selected search result
22 | resultsView.update(model.getSearchResultsPage());
23 |
24 | // 1) Updating bookmarks view
25 | bookmarksView.update(model.state.bookmarks);
26 |
27 | // 2) Loading recipe
28 | await model.loadRecipe(id);
29 |
30 | // 3) Rendering recipe
31 | recipeView.render(model.state.recipe);
32 | } catch (err) {
33 | recipeView.renderError();
34 | console.error(err);
35 | }
36 | };
37 |
38 | const controlSearchResults = async function () {
39 | try {
40 | resultsView.renderSpinner();
41 |
42 | // 1) Get search query
43 | const query = searchView.getQuery();
44 | if (!query) return;
45 |
46 | // 2) Load search results
47 | await model.loadSearchResults(query);
48 |
49 | // 3) Render results
50 | resultsView.render(model.getSearchResultsPage());
51 |
52 | // 4) Render initial pagination buttons
53 | paginationView.render(model.state.search);
54 | } catch (err) {
55 | console.log(err);
56 | }
57 | };
58 |
59 | const controlPagination = function (goToPage) {
60 | // 1) Render NEW results
61 | resultsView.render(model.getSearchResultsPage(goToPage));
62 |
63 | // 2) Render NEW pagination buttons
64 | paginationView.render(model.state.search);
65 | };
66 |
67 | const controlServings = function (newServings) {
68 | // Update the recipe servings (in state)
69 | model.updateServings(newServings);
70 |
71 | // Update the recipe view
72 | recipeView.update(model.state.recipe);
73 | };
74 |
75 | const controlAddBookmark = function () {
76 | // 1) Add/remove bookmark
77 | if (!model.state.recipe.bookmarked) model.addBookmark(model.state.recipe);
78 | else model.deleteBookmark(model.state.recipe.id);
79 |
80 | // 2) Update recipe view
81 | recipeView.update(model.state.recipe);
82 |
83 | // 3) Render bookmarks
84 | bookmarksView.render(model.state.bookmarks);
85 | };
86 |
87 | const controlBookmarks = function () {
88 | bookmarksView.render(model.state.bookmarks);
89 | };
90 |
91 | const controlAddRecipe = async function (newRecipe) {
92 | try {
93 | // Show loading spinner
94 | addRecipeView.renderSpinner();
95 |
96 | // Upload the new recipe data
97 | await model.uploadRecipe(newRecipe);
98 | console.log(model.state.recipe);
99 |
100 | // Render recipe
101 | recipeView.render(model.state.recipe);
102 |
103 | // Success message
104 | addRecipeView.renderMessage();
105 |
106 | // Render bookmark view
107 | bookmarksView.render(model.state.bookmarks);
108 |
109 | // Change ID in URL
110 | window.history.pushState(null, '', `#${model.state.recipe.id}`);
111 |
112 | // Close form window
113 | setTimeout(function () {
114 | addRecipeView.toggleWindow();
115 | }, MODAL_CLOSE_SEC * 1000);
116 | } catch (err) {
117 | console.error('💥', err);
118 | addRecipeView.renderError(err.message);
119 | }
120 | };
121 |
122 | const init = function () {
123 | bookmarksView.addHandlerRender(controlBookmarks);
124 | recipeView.addHandlerRender(controlRecipes);
125 | recipeView.addHandlerUpdateServings(controlServings);
126 | recipeView.addHandlerAddBookmark(controlAddBookmark);
127 | searchView.addHandlerSearch(controlSearchResults);
128 | paginationView.addHandlerClick(controlPagination);
129 | addRecipeView.addHandlerUpload(controlAddRecipe);
130 | };
131 | init();
132 |
--------------------------------------------------------------------------------
/18-forkify/final/src/js/helpers.js:
--------------------------------------------------------------------------------
1 | import { async } from 'regenerator-runtime';
2 | import { TIMEOUT_SEC } from './config.js';
3 |
4 | const timeout = function (s) {
5 | return new Promise(function (_, reject) {
6 | setTimeout(function () {
7 | reject(new Error(`Request took too long! Timeout after ${s} second`));
8 | }, s * 1000);
9 | });
10 | };
11 |
12 | export const AJAX = async function (url, uploadData = undefined) {
13 | try {
14 | const fetchPro = uploadData
15 | ? fetch(url, {
16 | method: 'POST',
17 | headers: {
18 | 'Content-Type': 'application/json',
19 | },
20 | body: JSON.stringify(uploadData),
21 | })
22 | : fetch(url);
23 |
24 | const res = await Promise.race([fetchPro, timeout(TIMEOUT_SEC)]);
25 | const data = await res.json();
26 |
27 | if (!res.ok) throw new Error(`${data.message} (${res.status})`);
28 | return data;
29 | } catch (err) {
30 | throw err;
31 | }
32 | };
33 |
34 | /*
35 | export const getJSON = async function (url) {
36 | try {
37 | const fetchPro = fetch(url);
38 | const res = await Promise.race([fetchPro, timeout(TIMEOUT_SEC)]);
39 | const data = await res.json();
40 |
41 | if (!res.ok) throw new Error(`${data.message} (${res.status})`);
42 | return data;
43 | } catch (err) {
44 | throw err;
45 | }
46 | };
47 |
48 | export const sendJSON = async function (url, uploadData) {
49 | try {
50 | const fetchPro = fetch(url, {
51 | method: 'POST',
52 | headers: {
53 | 'Content-Type': 'application/json',
54 | },
55 | body: JSON.stringify(uploadData),
56 | });
57 |
58 | const res = await Promise.race([fetchPro, timeout(TIMEOUT_SEC)]);
59 | const data = await res.json();
60 |
61 | if (!res.ok) throw new Error(`${data.message} (${res.status})`);
62 | return data;
63 | } catch (err) {
64 | throw err;
65 | }
66 | };
67 | */
68 |
--------------------------------------------------------------------------------
/18-forkify/final/src/js/model.js:
--------------------------------------------------------------------------------
1 | import { async } from 'regenerator-runtime';
2 | import { API_URL, RES_PER_PAGE, KEY } from './config.js';
3 | // import { getJSON, sendJSON } from './helpers.js';
4 | import { AJAX } from './helpers.js';
5 |
6 | export const state = {
7 | recipe: {},
8 | search: {
9 | query: '',
10 | results: [],
11 | page: 1,
12 | resultsPerPage: RES_PER_PAGE,
13 | },
14 | bookmarks: [],
15 | };
16 |
17 | const createRecipeObject = function (data) {
18 | const { recipe } = data.data;
19 | return {
20 | id: recipe.id,
21 | title: recipe.title,
22 | publisher: recipe.publisher,
23 | sourceUrl: recipe.source_url,
24 | image: recipe.image_url,
25 | servings: recipe.servings,
26 | cookingTime: recipe.cooking_time,
27 | ingredients: recipe.ingredients,
28 | ...(recipe.key && { key: recipe.key }),
29 | };
30 | };
31 |
32 | export const loadRecipe = async function (id) {
33 | try {
34 | const data = await AJAX(`${API_URL}${id}?key=${KEY}`);
35 | state.recipe = createRecipeObject(data);
36 |
37 | if (state.bookmarks.some(bookmark => bookmark.id === id))
38 | state.recipe.bookmarked = true;
39 | else state.recipe.bookmarked = false;
40 |
41 | console.log(state.recipe);
42 | } catch (err) {
43 | // Temp error handling
44 | console.error(`${err} 💥💥💥💥`);
45 | throw err;
46 | }
47 | };
48 |
49 | export const loadSearchResults = async function (query) {
50 | try {
51 | state.search.query = query;
52 |
53 | const data = await AJAX(`${API_URL}?search=${query}&key=${KEY}`);
54 | console.log(data);
55 |
56 | state.search.results = data.data.recipes.map(rec => {
57 | return {
58 | id: rec.id,
59 | title: rec.title,
60 | publisher: rec.publisher,
61 | image: rec.image_url,
62 | ...(rec.key && { key: rec.key }),
63 | };
64 | });
65 | state.search.page = 1;
66 | } catch (err) {
67 | console.error(`${err} 💥💥💥💥`);
68 | throw err;
69 | }
70 | };
71 |
72 | export const getSearchResultsPage = function (page = state.search.page) {
73 | state.search.page = page;
74 |
75 | const start = (page - 1) * state.search.resultsPerPage; // 0
76 | const end = page * state.search.resultsPerPage; // 9
77 |
78 | return state.search.results.slice(start, end);
79 | };
80 |
81 | export const updateServings = function (newServings) {
82 | state.recipe.ingredients.forEach(ing => {
83 | ing.quantity = (ing.quantity * newServings) / state.recipe.servings;
84 | // newQt = oldQt * newServings / oldServings // 2 * 8 / 4 = 4
85 | });
86 |
87 | state.recipe.servings = newServings;
88 | };
89 |
90 | const persistBookmarks = function () {
91 | localStorage.setItem('bookmarks', JSON.stringify(state.bookmarks));
92 | };
93 |
94 | export const addBookmark = function (recipe) {
95 | // Add bookmark
96 | state.bookmarks.push(recipe);
97 |
98 | // Mark current recipe as bookmarked
99 | if (recipe.id === state.recipe.id) state.recipe.bookmarked = true;
100 |
101 | persistBookmarks();
102 | };
103 |
104 | export const deleteBookmark = function (id) {
105 | // Delete bookmark
106 | const index = state.bookmarks.findIndex(el => el.id === id);
107 | state.bookmarks.splice(index, 1);
108 |
109 | // Mark current recipe as NOT bookmarked
110 | if (id === state.recipe.id) state.recipe.bookmarked = false;
111 |
112 | persistBookmarks();
113 | };
114 |
115 | const init = function () {
116 | const storage = localStorage.getItem('bookmarks');
117 | if (storage) state.bookmarks = JSON.parse(storage);
118 | };
119 | init();
120 |
121 | const clearBookmarks = function () {
122 | localStorage.clear('bookmarks');
123 | };
124 | // clearBookmarks();
125 |
126 | export const uploadRecipe = async function (newRecipe) {
127 | try {
128 | const ingredients = Object.entries(newRecipe)
129 | .filter(entry => entry[0].startsWith('ingredient') && entry[1] !== '')
130 | .map(ing => {
131 | const ingArr = ing[1].split(',').map(el => el.trim());
132 | // const ingArr = ing[1].replaceAll(' ', '').split(',');
133 | if (ingArr.length !== 3)
134 | throw new Error(
135 | 'Wrong ingredient fromat! Please use the correct format :)'
136 | );
137 |
138 | const [quantity, unit, description] = ingArr;
139 |
140 | return { quantity: quantity ? +quantity : null, unit, description };
141 | });
142 |
143 | const recipe = {
144 | title: newRecipe.title,
145 | source_url: newRecipe.sourceUrl,
146 | image_url: newRecipe.image,
147 | publisher: newRecipe.publisher,
148 | cooking_time: +newRecipe.cookingTime,
149 | servings: +newRecipe.servings,
150 | ingredients,
151 | };
152 |
153 | const data = await AJAX(`${API_URL}?key=${KEY}`, recipe);
154 | state.recipe = createRecipeObject(data);
155 | addBookmark(state.recipe);
156 | } catch (err) {
157 | throw err;
158 | }
159 | };
160 |
--------------------------------------------------------------------------------
/18-forkify/final/src/js/views/View.js:
--------------------------------------------------------------------------------
1 | import icons from 'url:../../img/icons.svg'; // Parcel 2
2 |
3 | export default class View {
4 | _data;
5 |
6 | /**
7 | * Render the received object to the DOM
8 | * @param {Object | Object[]} data The data to be rendered (e.g. recipe)
9 | * @param {boolean} [render=true] If false, create markup string instead of rendering to the DOM
10 | * @returns {undefined | string} A markup string is returned if render=false
11 | * @this {Object} View instance
12 | * @author Jonas Schmedtmann
13 | * @todo Finish implementation
14 | */
15 | render(data, render = true) {
16 | if (!data || (Array.isArray(data) && data.length === 0))
17 | return this.renderError();
18 |
19 | this._data = data;
20 | const markup = this._generateMarkup();
21 |
22 | if (!render) return markup;
23 |
24 | this._clear();
25 | this._parentElement.insertAdjacentHTML('afterbegin', markup);
26 | }
27 |
28 | update(data) {
29 | this._data = data;
30 | const newMarkup = this._generateMarkup();
31 |
32 | const newDOM = document.createRange().createContextualFragment(newMarkup);
33 | const newElements = Array.from(newDOM.querySelectorAll('*'));
34 | const curElements = Array.from(this._parentElement.querySelectorAll('*'));
35 |
36 | newElements.forEach((newEl, i) => {
37 | const curEl = curElements[i];
38 | // console.log(curEl, newEl.isEqualNode(curEl));
39 |
40 | // Updates changed TEXT
41 | if (
42 | !newEl.isEqualNode(curEl) &&
43 | newEl.firstChild?.nodeValue.trim() !== ''
44 | ) {
45 | // console.log('💥', newEl.firstChild.nodeValue.trim());
46 | curEl.textContent = newEl.textContent;
47 | }
48 |
49 | // Updates changed ATTRIBUES
50 | if (!newEl.isEqualNode(curEl))
51 | Array.from(newEl.attributes).forEach(attr =>
52 | curEl.setAttribute(attr.name, attr.value)
53 | );
54 | });
55 | }
56 |
57 | _clear() {
58 | this._parentElement.innerHTML = '';
59 | }
60 |
61 | renderSpinner() {
62 | const markup = `
63 |
64 |
65 |
66 |
67 |
68 | `;
69 | this._clear();
70 | this._parentElement.insertAdjacentHTML('afterbegin', markup);
71 | }
72 |
73 | renderError(message = this._errorMessage) {
74 | const markup = `
75 |
76 |
77 |
78 |
79 |
80 |
81 |
${message}
82 |
83 | `;
84 | this._clear();
85 | this._parentElement.insertAdjacentHTML('afterbegin', markup);
86 | }
87 |
88 | renderMessage(message = this._message) {
89 | const markup = `
90 |
91 |
92 |
93 |
94 |
95 |
96 |
${message}
97 |
98 | `;
99 | this._clear();
100 | this._parentElement.insertAdjacentHTML('afterbegin', markup);
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/18-forkify/final/src/js/views/addRecipeView.js:
--------------------------------------------------------------------------------
1 | import View from './View.js';
2 | import icons from 'url:../../img/icons.svg'; // Parcel 2
3 |
4 | class AddRecipeView extends View {
5 | _parentElement = document.querySelector('.upload');
6 | _message = 'Recipe was successfully uploaded :)';
7 |
8 | _window = document.querySelector('.add-recipe-window');
9 | _overlay = document.querySelector('.overlay');
10 | _btnOpen = document.querySelector('.nav__btn--add-recipe');
11 | _btnClose = document.querySelector('.btn--close-modal');
12 |
13 | constructor() {
14 | super();
15 | this._addHandlerShowWindow();
16 | this._addHandlerHideWindow();
17 | }
18 |
19 | toggleWindow() {
20 | this._overlay.classList.toggle('hidden');
21 | this._window.classList.toggle('hidden');
22 | }
23 |
24 | _addHandlerShowWindow() {
25 | this._btnOpen.addEventListener('click', this.toggleWindow.bind(this));
26 | }
27 |
28 | _addHandlerHideWindow() {
29 | this._btnClose.addEventListener('click', this.toggleWindow.bind(this));
30 | this._overlay.addEventListener('click', this.toggleWindow.bind(this));
31 | }
32 |
33 | addHandlerUpload(handler) {
34 | this._parentElement.addEventListener('submit', function (e) {
35 | e.preventDefault();
36 | const dataArr = [...new FormData(this)];
37 | const data = Object.fromEntries(dataArr);
38 | handler(data);
39 | });
40 | }
41 |
42 | _generateMarkup() {}
43 | }
44 |
45 | export default new AddRecipeView();
46 |
--------------------------------------------------------------------------------
/18-forkify/final/src/js/views/bookmarksView.js:
--------------------------------------------------------------------------------
1 | import View from './View.js';
2 | import previewView from './previewView.js';
3 | import icons from 'url:../../img/icons.svg'; // Parcel 2
4 |
5 | class BookmarksView extends View {
6 | _parentElement = document.querySelector('.bookmarks__list');
7 | _errorMessage = 'No bookmarks yet. Find a nice recipe and bookmark it ;)';
8 | _message = '';
9 |
10 | addHandlerRender(handler) {
11 | window.addEventListener('load', handler);
12 | }
13 |
14 | _generateMarkup() {
15 | return this._data
16 | .map(bookmark => previewView.render(bookmark, false))
17 | .join('');
18 | }
19 | }
20 |
21 | export default new BookmarksView();
22 |
--------------------------------------------------------------------------------
/18-forkify/final/src/js/views/paginationView.js:
--------------------------------------------------------------------------------
1 | import View from './View.js';
2 | import icons from 'url:../../img/icons.svg'; // Parcel 2
3 |
4 | class PaginationView extends View {
5 | _parentElement = document.querySelector('.pagination');
6 |
7 | addHandlerClick(handler) {
8 | this._parentElement.addEventListener('click', function (e) {
9 | const btn = e.target.closest('.btn--inline');
10 | if (!btn) return;
11 |
12 | const goToPage = +btn.dataset.goto;
13 | handler(goToPage);
14 | });
15 | }
16 |
17 | _generateMarkup() {
18 | const curPage = this._data.page;
19 | const numPages = Math.ceil(
20 | this._data.results.length / this._data.resultsPerPage
21 | );
22 |
23 | // Page 1, and there are other pages
24 | if (curPage === 1 && numPages > 1) {
25 | return `
26 |
34 | `;
35 | }
36 |
37 | // Last page
38 | if (curPage === numPages && numPages > 1) {
39 | return `
40 |
48 | `;
49 | }
50 |
51 | // Other page
52 | if (curPage < numPages) {
53 | return `
54 |
62 |
70 | `;
71 | }
72 |
73 | // Page 1, and there are NO other pages
74 | return '';
75 | }
76 | }
77 |
78 | export default new PaginationView();
79 |
--------------------------------------------------------------------------------
/18-forkify/final/src/js/views/previewView.js:
--------------------------------------------------------------------------------
1 | import View from './View.js';
2 | import icons from 'url:../../img/icons.svg'; // Parcel 2
3 |
4 | class PreviewView extends View {
5 | _parentElement = '';
6 |
7 | _generateMarkup() {
8 | const id = window.location.hash.slice(1);
9 |
10 | return `
11 |
12 |
15 |
16 |
17 |
18 |
19 |
${this._data.title}
20 |
${this._data.publisher}
21 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | `;
32 | }
33 | }
34 |
35 | export default new PreviewView();
36 |
--------------------------------------------------------------------------------
/18-forkify/final/src/js/views/recipeView.js:
--------------------------------------------------------------------------------
1 | import View from './View.js';
2 |
3 | // import icons from '../img/icons.svg'; // Parcel 1
4 | import icons from 'url:../../img/icons.svg'; // Parcel 2
5 | import { Fraction } from 'fractional';
6 |
7 | class RecipeView extends View {
8 | _parentElement = document.querySelector('.recipe');
9 | _errorMessage = 'We could not find that recipe. Please try another one!';
10 | _message = '';
11 |
12 | addHandlerRender(handler) {
13 | ['hashchange', 'load'].forEach(ev => window.addEventListener(ev, handler));
14 | }
15 |
16 | addHandlerUpdateServings(handler) {
17 | this._parentElement.addEventListener('click', function (e) {
18 | const btn = e.target.closest('.btn--update-servings');
19 | if (!btn) return;
20 | const { updateTo } = btn.dataset;
21 | if (+updateTo > 0) handler(+updateTo);
22 | });
23 | }
24 |
25 | addHandlerAddBookmark(handler) {
26 | this._parentElement.addEventListener('click', function (e) {
27 | const btn = e.target.closest('.btn--bookmark');
28 | if (!btn) return;
29 | handler();
30 | });
31 | }
32 |
33 | _generateMarkup() {
34 | return `
35 |
36 |
39 |
40 | ${this._data.title}
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | ${
50 | this._data.cookingTime
51 | }
52 | minutes
53 |
54 |
55 |
56 |
57 |
58 |
${
59 | this._data.servings
60 | }
61 |
servings
62 |
63 |
64 |
67 |
68 |
69 |
70 |
71 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
91 |
92 |
93 |
94 |
95 |
96 |
Recipe ingredients
97 |
98 | ${this._data.ingredients.map(this._generateMarkupIngredient).join('')}
99 |
100 |
101 |
102 |
How to cook it
103 |
104 | This recipe was carefully designed and tested by
105 | ${
106 | this._data.publisher
107 | } . Please check out
108 | directions at their website.
109 |
110 |
115 | Directions
116 |
117 |
118 |
119 |
120 |
121 | `;
122 | }
123 |
124 | _generateMarkupIngredient(ing) {
125 | return `
126 |
127 |
128 |
129 |
130 | ${
131 | ing.quantity ? new Fraction(ing.quantity).toString() : ''
132 | }
133 |
134 | ${ing.unit}
135 | ${ing.description}
136 |
137 |
138 | `;
139 | }
140 | }
141 |
142 | export default new RecipeView();
143 |
--------------------------------------------------------------------------------
/18-forkify/final/src/js/views/resultsView.js:
--------------------------------------------------------------------------------
1 | import View from './View.js';
2 | import previewView from './previewView.js';
3 | import icons from 'url:../../img/icons.svg'; // Parcel 2
4 |
5 | class ResultsView extends View {
6 | _parentElement = document.querySelector('.results');
7 | _errorMessage = 'No recipes found for your query! Please try again ;)';
8 | _message = '';
9 |
10 | _generateMarkup() {
11 | return this._data.map(result => previewView.render(result, false)).join('');
12 | }
13 | }
14 |
15 | export default new ResultsView();
16 |
--------------------------------------------------------------------------------
/18-forkify/final/src/js/views/searchView.js:
--------------------------------------------------------------------------------
1 | class SearchView {
2 | _parentEl = document.querySelector('.search');
3 |
4 | getQuery() {
5 | const query = this._parentEl.querySelector('.search__field').value;
6 | this._clearInput();
7 | return query;
8 | }
9 |
10 | _clearInput() {
11 | this._parentEl.querySelector('.search__field').value = '';
12 | }
13 |
14 | addHandlerSearch(handler) {
15 | this._parentEl.addEventListener('submit', function (e) {
16 | e.preventDefault();
17 | handler();
18 | });
19 | }
20 | }
21 |
22 | export default new SearchView();
23 |
--------------------------------------------------------------------------------
/18-forkify/final/src/sass/_base.scss:
--------------------------------------------------------------------------------
1 | // $color-primary: #f59a83;
2 | $color-primary: #f38e82;
3 | $color-grad-1: #fbdb89;
4 | $color-grad-2: #f48982;
5 |
6 | $color-grey-light-1: #f9f5f3; // Light background
7 | $color-grey-light-2: #f2efee; // Light lines
8 | $color-grey-light-3: #d3c7c3; // Light text (placeholder)
9 | $color-grey-dark-1: #615551; // Normal text
10 | $color-grey-dark-2: #918581; // Lighter text
11 |
12 | $gradient: linear-gradient(to right bottom, $color-grad-1, $color-grad-2);
13 |
14 | $bp-large: 78.15em; // 1250px
15 | $bp-medium: 61.25em; // 980px
16 | $bp-small: 37.5em; // 600px
17 | $bp-smallest: 31.25em; // 500px
18 |
19 | * {
20 | margin: 0;
21 | padding: 0;
22 | }
23 |
24 | *,
25 | *::before,
26 | *::after {
27 | box-sizing: inherit;
28 | }
29 |
30 | html {
31 | box-sizing: border-box;
32 | font-size: 62.5%;
33 |
34 | @media only screen and (max-width: $bp-medium) {
35 | font-size: 50%;
36 | }
37 | }
38 |
39 | body {
40 | font-family: 'Nunito Sans', sans-serif;
41 | font-weight: 400;
42 | line-height: 1.6;
43 | color: $color-grey-dark-1;
44 | background-image: $gradient;
45 | background-size: cover;
46 | background-repeat: no-repeat;
47 | min-height: calc(100vh - 2 * 4vw);
48 | }
49 |
50 | .container {
51 | max-width: 120rem;
52 | min-height: 117rem;
53 | margin: 4vw auto;
54 | background-color: #fff;
55 | border-radius: 9px;
56 | overflow: hidden;
57 | box-shadow: 0 2rem 6rem 0.5rem rgba($color-grey-dark-1, 0.2);
58 |
59 | display: grid;
60 | grid-template-rows: 10rem minmax(100rem, auto);
61 | grid-template-columns: 1fr 2fr;
62 | grid-template-areas:
63 | 'head head'
64 | 'list recipe';
65 |
66 | @media only screen and (max-width: $bp-large) {
67 | max-width: 100%;
68 | margin: 0;
69 | border-radius: 0;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/18-forkify/final/src/sass/_components.scss:
--------------------------------------------------------------------------------
1 | %btn {
2 | background-image: $gradient;
3 | border-radius: 10rem;
4 | border: none;
5 | text-transform: uppercase;
6 | color: #fff;
7 | cursor: pointer;
8 | display: flex;
9 | align-items: center;
10 | transition: all 0.2s;
11 |
12 | &:hover {
13 | transform: scale(1.05);
14 | }
15 |
16 | &:focus {
17 | outline: none;
18 | }
19 |
20 | & > *:first-child {
21 | margin-right: 1rem;
22 | }
23 | }
24 |
25 | .btn {
26 | @extend %btn;
27 |
28 | padding: 1.5rem 4rem;
29 | font-size: 1.5rem;
30 | font-weight: 600;
31 |
32 | svg {
33 | height: 2.25rem;
34 | width: 2.25rem;
35 | fill: currentColor;
36 | }
37 | }
38 |
39 | .btn--small {
40 | &,
41 | &:link,
42 | &:visited {
43 | @extend %btn;
44 |
45 | font-size: 1.4rem;
46 | font-weight: 600;
47 | padding: 1.25rem 2.25rem;
48 | text-decoration: none;
49 |
50 | svg {
51 | height: 1.75rem;
52 | width: 1.75rem;
53 | fill: currentColor;
54 | }
55 | }
56 | }
57 |
58 | .btn--inline {
59 | color: $color-primary;
60 | font-size: 1.3rem;
61 | font-weight: 600;
62 | border: none;
63 | background-color: $color-grey-light-1;
64 | padding: 0.8rem 1.2rem;
65 | border-radius: 10rem;
66 | cursor: pointer;
67 |
68 | display: flex;
69 | align-items: center;
70 | transition: all 0.2s;
71 |
72 | svg {
73 | height: 1.6rem;
74 | width: 1.6rem;
75 | fill: currentColor;
76 | margin: 0 0.2rem;
77 | }
78 |
79 | span {
80 | margin: 0 0.4rem;
81 | }
82 |
83 | &:hover {
84 | color: $color-grad-2;
85 | background-color: $color-grey-light-2;
86 | }
87 |
88 | &:focus {
89 | outline: none;
90 | }
91 | }
92 |
93 | .btn--round {
94 | background-image: $gradient;
95 | border-radius: 50%;
96 | border: none;
97 | cursor: pointer;
98 | height: 4.5rem;
99 | width: 4.5rem;
100 | // margin-left: auto;
101 | transition: all 0.2s;
102 |
103 | display: flex;
104 | align-items: center;
105 | justify-content: center;
106 |
107 | &:hover {
108 | transform: scale(1.07);
109 | }
110 |
111 | &:focus {
112 | outline: none;
113 | }
114 |
115 | svg {
116 | height: 2.5rem;
117 | width: 2.5rem;
118 | fill: #fff;
119 | }
120 | }
121 |
122 | .btn--tiny {
123 | height: 2rem;
124 | width: 2rem;
125 | border: none;
126 | background: none;
127 | cursor: pointer;
128 |
129 | svg {
130 | height: 100%;
131 | width: 100%;
132 | fill: $color-primary;
133 | transition: all 0.3s;
134 | }
135 |
136 | &:focus {
137 | outline: none;
138 | }
139 |
140 | &:hover svg {
141 | fill: $color-grad-2;
142 | transform: translateY(-1px);
143 | }
144 |
145 | &:active svg {
146 | fill: $color-grad-2;
147 | transform: translateY(0);
148 | }
149 |
150 | &:not(:last-child) {
151 | margin-right: 0.3rem;
152 | }
153 | }
154 |
155 | .heading--2 {
156 | font-size: 2rem;
157 | font-weight: 700;
158 | color: $color-primary;
159 | text-transform: uppercase;
160 | margin-bottom: 2.5rem;
161 | text-align: center;
162 | // transform: skewY(-3deg);
163 | }
164 |
165 | .link:link,
166 | .link:visited {
167 | color: $color-grey-dark-2;
168 | }
169 |
170 | .spinner {
171 | margin: 5rem auto;
172 | text-align: center;
173 |
174 | svg {
175 | height: 6rem;
176 | width: 6rem;
177 | fill: $color-primary;
178 | animation: rotate 2s infinite linear;
179 | }
180 | }
181 |
182 | @keyframes rotate {
183 | 0% {
184 | transform: rotate(0);
185 | }
186 |
187 | 100% {
188 | transform: rotate(360deg);
189 | }
190 | }
191 |
192 | .message,
193 | .error {
194 | max-width: 40rem;
195 | margin: 0 auto;
196 | padding: 5rem 4rem;
197 |
198 | display: flex;
199 |
200 | svg {
201 | height: 3rem;
202 | width: 3rem;
203 | fill: $color-primary;
204 | transform: translateY(-0.3rem);
205 | }
206 |
207 | p {
208 | margin-left: 1.5rem;
209 | font-size: 1.8rem;
210 | line-height: 1.5;
211 | font-weight: 600;
212 | }
213 | }
214 |
--------------------------------------------------------------------------------
/18-forkify/final/src/sass/_header.scss:
--------------------------------------------------------------------------------
1 | .header {
2 | grid-area: head;
3 | background-color: $color-grey-light-1;
4 | display: flex;
5 | align-items: center;
6 | justify-content: space-between;
7 |
8 | &__logo {
9 | margin-left: 4rem;
10 | height: 4.6rem;
11 | display: block;
12 | }
13 | }
14 |
15 | .search {
16 | background-color: #fff;
17 | border-radius: 10rem;
18 | display: flex;
19 | align-items: center;
20 | padding-left: 3rem;
21 | transition: all 0.3s;
22 |
23 | &:focus-within {
24 | transform: translateY(-2px);
25 | box-shadow: 0 0.7rem 3rem rgba($color-grey-dark-1, 0.08);
26 | }
27 |
28 | &__field {
29 | border: none;
30 | background: none;
31 | font-family: inherit;
32 | color: inherit;
33 | font-size: 1.7rem;
34 | width: 30rem;
35 |
36 | &:focus {
37 | outline: none;
38 | }
39 |
40 | &::placeholder {
41 | color: $color-grey-light-3;
42 | }
43 |
44 | @media only screen and (max-width: $bp-medium) {
45 | width: auto;
46 |
47 | &::placeholder {
48 | color: white;
49 | }
50 | }
51 | }
52 |
53 | &__btn {
54 | font-weight: 600;
55 | font-family: inherit;
56 | }
57 | }
58 |
59 | .nav {
60 | align-self: stretch;
61 | margin-right: 2.5rem;
62 |
63 | &__list {
64 | list-style: none;
65 | display: flex;
66 | height: 100%;
67 | }
68 |
69 | &__item {
70 | position: relative;
71 | }
72 |
73 | &__btn {
74 | height: 100%;
75 | font-family: inherit;
76 | color: inherit;
77 | font-size: 1.4rem;
78 | font-weight: 700;
79 | text-transform: uppercase;
80 | background: none;
81 | border: none;
82 | cursor: pointer;
83 | padding: 0 1.5rem;
84 | transition: all 0.3s;
85 |
86 | display: flex;
87 | align-items: center;
88 |
89 | svg {
90 | height: 2.4rem;
91 | width: 2.4rem;
92 | fill: $color-primary;
93 | margin-right: 0.7rem;
94 | transform: translateY(-1px);
95 | }
96 |
97 | &:focus {
98 | outline: none;
99 | }
100 |
101 | &:hover {
102 | background-color: $color-grey-light-2;
103 | }
104 | }
105 | }
106 |
107 | .bookmarks {
108 | padding: 1rem 0;
109 | position: absolute;
110 | // right: 0;
111 | right: -2.5rem;
112 | z-index: 10;
113 | width: 40rem;
114 | background-color: #fff;
115 | box-shadow: 0 0.8rem 5rem 2rem rgba($color-grey-dark-1, 0.1);
116 |
117 | visibility: hidden;
118 | opacity: 0;
119 | transition: all 0.5s 0.2s;
120 |
121 | &__list {
122 | list-style: none;
123 | }
124 |
125 | &__field {
126 | cursor: pointer;
127 | padding: 0 4rem;
128 |
129 | display: flex;
130 | align-items: center;
131 | height: 100%;
132 | transition: all 0.3s;
133 |
134 | &:hover {
135 | background-color: $color-grey-light-2;
136 | }
137 | }
138 |
139 | &:hover,
140 | .nav__btn--bookmarks:hover + & {
141 | visibility: visible;
142 | opacity: 1;
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/18-forkify/final/src/sass/_preview.scss:
--------------------------------------------------------------------------------
1 | .preview {
2 | &__link {
3 | &:link,
4 | &:visited {
5 | display: flex;
6 | align-items: center;
7 | padding: 1.5rem 3.25rem;
8 | transition: all 0.3s;
9 | border-right: 1px solid #fff;
10 | text-decoration: none;
11 | }
12 |
13 | &:hover {
14 | background-color: $color-grey-light-1;
15 | transform: translateY(-2px);
16 | }
17 |
18 | &--active {
19 | background-color: $color-grey-light-1;
20 | }
21 | }
22 |
23 | &__fig {
24 | flex: 0 0 5.8rem;
25 | border-radius: 50%;
26 | overflow: hidden;
27 | height: 5.8rem;
28 | margin-right: 2rem;
29 | position: relative;
30 | backface-visibility: hidden;
31 |
32 | &::before {
33 | content: '';
34 | display: block;
35 | height: 100%;
36 | width: 100%;
37 | position: absolute;
38 | top: 0;
39 | left: 0;
40 | background-image: linear-gradient(
41 | to right bottom,
42 | $color-grad-1,
43 | $color-grad-2
44 | );
45 | opacity: 0.4;
46 | }
47 |
48 | img {
49 | display: block;
50 | width: 100%;
51 | height: 100%;
52 | object-fit: cover;
53 | transition: all 0.3s;
54 | }
55 | }
56 |
57 | &__data {
58 | display: grid;
59 | width: 100%;
60 | grid-template-columns: 1fr 2rem;
61 | row-gap: 0.1rem;
62 | align-items: center;
63 | }
64 |
65 | &__title {
66 | grid-column: 1/-1;
67 | font-size: 1.45rem;
68 | color: $color-primary;
69 | text-transform: uppercase;
70 | font-weight: 600;
71 |
72 | // This is how text is truncated!
73 | text-overflow: ellipsis;
74 | max-width: 25rem;
75 | white-space: nowrap;
76 | overflow: hidden;
77 | }
78 |
79 | &__publisher {
80 | font-size: 1.15rem;
81 | color: $color-grey-dark-2;
82 | text-transform: uppercase;
83 | font-weight: 600;
84 | }
85 |
86 | &__user-generated {
87 | background-color: darken($color-grey-light-2, 2%);
88 |
89 | display: flex;
90 | align-items: center;
91 | justify-content: center;
92 | height: 2rem;
93 | width: 2rem;
94 | border-radius: 10rem;
95 |
96 | margin-left: auto;
97 | margin-right: 1.75rem;
98 |
99 | svg {
100 | height: 1.2rem;
101 | width: 1.2rem;
102 | fill: $color-primary;
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/18-forkify/final/src/sass/_recipe.scss:
--------------------------------------------------------------------------------
1 | .recipe {
2 | background-color: $color-grey-light-1;
3 |
4 | ///////////
5 | // FIGURE
6 | &__fig {
7 | height: 32rem;
8 | position: relative;
9 | // transform: scale(1.04) translateY(-1px);
10 | transform-origin: top;
11 |
12 | &::before {
13 | content: '';
14 | display: block;
15 | height: 100%;
16 | width: 100%;
17 | position: absolute;
18 | top: 0;
19 | left: 0;
20 | background-image: linear-gradient(
21 | to right bottom,
22 | $color-grad-1,
23 | $color-grad-2
24 | );
25 | opacity: 0.6;
26 | }
27 | }
28 |
29 | &__img {
30 | width: 100%;
31 | display: block;
32 | height: 100%;
33 | object-fit: cover;
34 | }
35 |
36 | &__title {
37 | position: absolute;
38 | bottom: 0;
39 | left: 50%;
40 | transform: translate(-50%, 20%) skewY(-6deg);
41 | color: #fff;
42 | font-weight: 700;
43 | font-size: 3.25rem;
44 | text-transform: uppercase;
45 | width: 50%;
46 | line-height: 1.95;
47 | text-align: center;
48 |
49 | span {
50 | -webkit-box-decoration-break: clone;
51 | box-decoration-break: clone;
52 | padding: 1.3rem 2rem;
53 | background-image: linear-gradient(
54 | to right bottom,
55 | $color-grad-1,
56 | $color-grad-2
57 | );
58 | }
59 |
60 | @media only screen and (max-width: $bp-medium) {
61 | width: 70%;
62 | }
63 | }
64 |
65 | ///////////
66 | // DETAILS
67 | &__details {
68 | display: flex;
69 | align-items: center;
70 | padding: 7.5rem 8rem 3.5rem 8rem;
71 | }
72 |
73 | &__info {
74 | font-size: 1.65rem;
75 | text-transform: uppercase;
76 | display: flex;
77 | align-items: center;
78 |
79 | &:not(:last-child) {
80 | margin-right: 4.5rem;
81 | }
82 | }
83 |
84 | &__info-icon {
85 | height: 2.35rem;
86 | width: 2.35rem;
87 | fill: $color-primary;
88 | margin-right: 1.15rem;
89 | }
90 |
91 | &__info-data {
92 | margin-right: 0.5rem;
93 | font-weight: 700;
94 | }
95 |
96 | &__info-buttons {
97 | display: flex;
98 | margin-left: 1.6rem;
99 | transform: translateY(-1px);
100 | }
101 |
102 | &__user-generated {
103 | background-color: darken($color-grey-light-2, 2%);
104 |
105 | display: flex;
106 | align-items: center;
107 | justify-content: center;
108 | height: 4rem;
109 | width: 4rem;
110 | border-radius: 10rem;
111 |
112 | margin-left: auto;
113 | margin-right: 1.75rem;
114 |
115 | svg {
116 | height: 2.25rem;
117 | width: 2.25rem;
118 | fill: $color-primary;
119 | }
120 | }
121 |
122 | ///////////
123 | // INGREDIENTS
124 | &__ingredients {
125 | padding: 5rem 8rem;
126 | font-size: 1.6rem;
127 | line-height: 1.4;
128 | background-color: $color-grey-light-2;
129 | display: flex;
130 | flex-direction: column;
131 | align-items: center;
132 | }
133 |
134 | &__ingredient-list {
135 | display: grid;
136 | grid-template-columns: 1fr 1fr;
137 | gap: 2.5rem 3rem;
138 | list-style: none;
139 | }
140 |
141 | &__ingredient {
142 | display: flex;
143 | }
144 |
145 | &__icon {
146 | height: 2rem;
147 | width: 2rem;
148 | fill: $color-primary;
149 | margin-right: 1.1rem;
150 | flex: 0 0 auto;
151 | margin-top: 0.1rem;
152 | }
153 |
154 | &__quantity {
155 | margin-right: 0.5rem;
156 | flex: 0 0 auto;
157 | }
158 |
159 | ///////////
160 | // DIRECTIONS
161 | &__directions {
162 | padding: 5rem 10rem;
163 | padding-bottom: 5rem;
164 | display: flex;
165 | flex-direction: column;
166 | align-items: center;
167 | }
168 |
169 | &__directions-text {
170 | font-size: 1.7rem;
171 | text-align: center;
172 | margin-bottom: 3.5rem;
173 | color: $color-grey-dark-2;
174 | }
175 |
176 | &__publisher {
177 | font-weight: 700;
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/18-forkify/final/src/sass/_searchResults.scss:
--------------------------------------------------------------------------------
1 | .search-results {
2 | padding: 3rem 0;
3 | display: flex;
4 | flex-direction: column;
5 | }
6 |
7 | .results {
8 | list-style: none;
9 | margin-bottom: 2rem;
10 | }
11 |
12 | .pagination {
13 | margin-top: auto;
14 | padding: 0 3.5rem;
15 |
16 | &::after {
17 | content: '';
18 | display: table;
19 | clear: both;
20 | }
21 |
22 | &__btn {
23 | &--prev {
24 | float: left;
25 | }
26 | &--next {
27 | float: right;
28 | }
29 | }
30 | }
31 |
32 | .copyright {
33 | color: $color-grey-dark-2;
34 | font-size: 1.2rem;
35 | padding: 0 3.5rem;
36 | margin-top: 4rem;
37 |
38 | .twitter-link:link,
39 | .twitter-link:visited {
40 | color: $color-grey-dark-2;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/18-forkify/final/src/sass/_upload.scss:
--------------------------------------------------------------------------------
1 | .add-recipe-window {
2 | position: fixed;
3 | top: 50%;
4 | left: 50%;
5 | transform: translate(-50%, -50%);
6 | width: 100rem;
7 | background-color: white;
8 | border-radius: 9px;
9 |
10 | padding: 5rem 6rem;
11 | box-shadow: 0 4rem 6rem rgba(0, 0, 0, 0.25);
12 | z-index: 1000;
13 | transition: all 0.5s;
14 |
15 | .btn--close-modal {
16 | font-family: inherit;
17 | color: inherit;
18 | position: absolute;
19 | top: 0.5rem;
20 | right: 1.6rem;
21 | font-size: 3.5rem;
22 | cursor: pointer;
23 | border: none;
24 | background: none;
25 | }
26 | }
27 |
28 | .overlay {
29 | position: fixed;
30 | top: 0;
31 | left: 0;
32 | width: 100%;
33 | height: 100%;
34 | background-color: rgba(0, 0, 0, 0.4);
35 | backdrop-filter: blur(4px);
36 | z-index: 100;
37 | transition: all 0.5s;
38 | }
39 |
40 | .hidden {
41 | visibility: hidden;
42 | opacity: 0;
43 | }
44 |
45 | .upload {
46 | display: grid;
47 | grid-template-columns: 1fr 1fr;
48 | gap: 4rem 6rem;
49 |
50 | &__column {
51 | display: grid;
52 | grid-template-columns: 1fr 2.8fr;
53 | align-items: center;
54 | gap: 1.5rem;
55 |
56 | & label {
57 | font-size: 1.5rem;
58 | font-weight: 600;
59 | color: inherit;
60 | }
61 |
62 | & input {
63 | font-size: 1.5rem;
64 | padding: 0.8rem 1rem;
65 | border: 1px solid #ddd;
66 | border-radius: 0.5rem;
67 | transition: all 0.2s;
68 |
69 | &::placeholder {
70 | color: $color-grey-light-3;
71 | }
72 |
73 | &:focus {
74 | outline: none;
75 | border: 1px solid $color-primary;
76 | background-color: $color-grey-light-1;
77 | }
78 | }
79 |
80 | & button {
81 | grid-column: 1 / span 2;
82 | justify-self: center;
83 | margin-top: 1rem;
84 | }
85 | }
86 |
87 | &__heading {
88 | font-size: 2.25rem;
89 | font-weight: 700;
90 | text-transform: uppercase;
91 | margin-bottom: 1rem;
92 | grid-column: 1/-1;
93 | }
94 |
95 | &__btn {
96 | grid-column: 1 / -1;
97 | justify-self: center;
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/18-forkify/final/src/sass/main.scss:
--------------------------------------------------------------------------------
1 | @import 'base';
2 | @import 'components';
3 | @import 'header';
4 | @import 'preview';
5 | @import 'searchResults';
6 | @import 'recipe';
7 | @import 'upload';
8 |
--------------------------------------------------------------------------------
/18-forkify/starter/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "arrowParens": "avoid"
4 | }
5 |
--------------------------------------------------------------------------------
/18-forkify/starter/forkify-architecture-recipe-loading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/18-forkify/starter/forkify-architecture-recipe-loading.png
--------------------------------------------------------------------------------
/18-forkify/starter/forkify-flowchart-part-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/18-forkify/starter/forkify-flowchart-part-1.png
--------------------------------------------------------------------------------
/18-forkify/starter/forkify-flowchart-part-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/18-forkify/starter/forkify-flowchart-part-2.png
--------------------------------------------------------------------------------
/18-forkify/starter/forkify-flowchart-part-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/18-forkify/starter/forkify-flowchart-part-3.png
--------------------------------------------------------------------------------
/18-forkify/starter/src/img/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/18-forkify/starter/src/img/favicon.png
--------------------------------------------------------------------------------
/18-forkify/starter/src/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/surajadkhari/complete-javascript-course/8201b01f2fcd274fb276c1c8e11e55847c6d451e/18-forkify/starter/src/img/logo.png
--------------------------------------------------------------------------------
/18-forkify/starter/src/js/controller.js:
--------------------------------------------------------------------------------
1 | const recipeContainer = document.querySelector('.recipe');
2 |
3 | const timeout = function (s) {
4 | return new Promise(function (_, reject) {
5 | setTimeout(function () {
6 | reject(new Error(`Request took too long! Timeout after ${s} second`));
7 | }, s * 1000);
8 | });
9 | };
10 |
11 | // https://forkify-api.herokuapp.com/v2
12 |
13 | ///////////////////////////////////////
14 |
--------------------------------------------------------------------------------
/18-forkify/starter/src/sass/_base.scss:
--------------------------------------------------------------------------------
1 | // $color-primary: #f59a83;
2 | $color-primary: #f38e82;
3 | $color-grad-1: #fbdb89;
4 | $color-grad-2: #f48982;
5 |
6 | $color-grey-light-1: #f9f5f3; // Light background
7 | $color-grey-light-2: #f2efee; // Light lines
8 | $color-grey-light-3: #d3c7c3; // Light text (placeholder)
9 | $color-grey-dark-1: #615551; // Normal text
10 | $color-grey-dark-2: #918581; // Lighter text
11 |
12 | $gradient: linear-gradient(to right bottom, $color-grad-1, $color-grad-2);
13 |
14 | $bp-large: 78.15em; // 1250px
15 | $bp-medium: 61.25em; // 980px
16 | $bp-small: 37.5em; // 600px
17 | $bp-smallest: 31.25em; // 500px
18 |
19 | * {
20 | margin: 0;
21 | padding: 0;
22 | }
23 |
24 | *,
25 | *::before,
26 | *::after {
27 | box-sizing: inherit;
28 | }
29 |
30 | html {
31 | box-sizing: border-box;
32 | font-size: 62.5%;
33 |
34 | @media only screen and (max-width: $bp-medium) {
35 | font-size: 50%;
36 | }
37 | }
38 |
39 | body {
40 | font-family: 'Nunito Sans', sans-serif;
41 | font-weight: 400;
42 | line-height: 1.6;
43 | color: $color-grey-dark-1;
44 | background-image: $gradient;
45 | background-size: cover;
46 | background-repeat: no-repeat;
47 | min-height: calc(100vh - 2 * 4vw);
48 | }
49 |
50 | .container {
51 | max-width: 120rem;
52 | min-height: 117rem;
53 | margin: 4vw auto;
54 | background-color: #fff;
55 | border-radius: 9px;
56 | overflow: hidden;
57 | box-shadow: 0 2rem 6rem 0.5rem rgba($color-grey-dark-1, 0.2);
58 |
59 | display: grid;
60 | grid-template-rows: 10rem minmax(100rem, auto);
61 | grid-template-columns: 1fr 2fr;
62 | grid-template-areas:
63 | 'head head'
64 | 'list recipe';
65 |
66 | @media only screen and (max-width: $bp-large) {
67 | max-width: 100%;
68 | margin: 0;
69 | border-radius: 0;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/18-forkify/starter/src/sass/_components.scss:
--------------------------------------------------------------------------------
1 | %btn {
2 | background-image: $gradient;
3 | border-radius: 10rem;
4 | border: none;
5 | text-transform: uppercase;
6 | color: #fff;
7 | cursor: pointer;
8 | display: flex;
9 | align-items: center;
10 | transition: all 0.2s;
11 |
12 | &:hover {
13 | transform: scale(1.05);
14 | }
15 |
16 | &:focus {
17 | outline: none;
18 | }
19 |
20 | & > *:first-child {
21 | margin-right: 1rem;
22 | }
23 | }
24 |
25 | .btn {
26 | @extend %btn;
27 |
28 | padding: 1.5rem 4rem;
29 | font-size: 1.5rem;
30 | font-weight: 600;
31 |
32 | svg {
33 | height: 2.25rem;
34 | width: 2.25rem;
35 | fill: currentColor;
36 | }
37 | }
38 |
39 | .btn--small {
40 | &,
41 | &:link,
42 | &:visited {
43 | @extend %btn;
44 |
45 | font-size: 1.4rem;
46 | font-weight: 600;
47 | padding: 1.25rem 2.25rem;
48 | text-decoration: none;
49 |
50 | svg {
51 | height: 1.75rem;
52 | width: 1.75rem;
53 | fill: currentColor;
54 | }
55 | }
56 | }
57 |
58 | .btn--inline {
59 | color: $color-primary;
60 | font-size: 1.3rem;
61 | font-weight: 600;
62 | border: none;
63 | background-color: $color-grey-light-1;
64 | padding: 0.8rem 1.2rem;
65 | border-radius: 10rem;
66 | cursor: pointer;
67 |
68 | display: flex;
69 | align-items: center;
70 | transition: all 0.2s;
71 |
72 | svg {
73 | height: 1.6rem;
74 | width: 1.6rem;
75 | fill: currentColor;
76 | margin: 0 0.2rem;
77 | }
78 |
79 | span {
80 | margin: 0 0.4rem;
81 | }
82 |
83 | &:hover {
84 | color: $color-grad-2;
85 | background-color: $color-grey-light-2;
86 | }
87 |
88 | &:focus {
89 | outline: none;
90 | }
91 | }
92 |
93 | .btn--round {
94 | background-image: $gradient;
95 | border-radius: 50%;
96 | border: none;
97 | cursor: pointer;
98 | height: 4.5rem;
99 | width: 4.5rem;
100 | // margin-left: auto;
101 | transition: all 0.2s;
102 |
103 | display: flex;
104 | align-items: center;
105 | justify-content: center;
106 |
107 | &:hover {
108 | transform: scale(1.07);
109 | }
110 |
111 | &:focus {
112 | outline: none;
113 | }
114 |
115 | svg {
116 | height: 2.5rem;
117 | width: 2.5rem;
118 | fill: #fff;
119 | }
120 | }
121 |
122 | .btn--tiny {
123 | height: 2rem;
124 | width: 2rem;
125 | border: none;
126 | background: none;
127 | cursor: pointer;
128 |
129 | svg {
130 | height: 100%;
131 | width: 100%;
132 | fill: $color-primary;
133 | transition: all 0.3s;
134 | }
135 |
136 | &:focus {
137 | outline: none;
138 | }
139 |
140 | &:hover svg {
141 | fill: $color-grad-2;
142 | transform: translateY(-1px);
143 | }
144 |
145 | &:active svg {
146 | fill: $color-grad-2;
147 | transform: translateY(0);
148 | }
149 |
150 | &:not(:last-child) {
151 | margin-right: 0.3rem;
152 | }
153 | }
154 |
155 | .heading--2 {
156 | font-size: 2rem;
157 | font-weight: 700;
158 | color: $color-primary;
159 | text-transform: uppercase;
160 | margin-bottom: 2.5rem;
161 | text-align: center;
162 | // transform: skewY(-3deg);
163 | }
164 |
165 | .link:link,
166 | .link:visited {
167 | color: $color-grey-dark-2;
168 | }
169 |
170 | .spinner {
171 | margin: 5rem auto;
172 | text-align: center;
173 |
174 | svg {
175 | height: 6rem;
176 | width: 6rem;
177 | fill: $color-primary;
178 | animation: rotate 2s infinite linear;
179 | }
180 | }
181 |
182 | @keyframes rotate {
183 | 0% {
184 | transform: rotate(0);
185 | }
186 |
187 | 100% {
188 | transform: rotate(360deg);
189 | }
190 | }
191 |
192 | .message,
193 | .error {
194 | max-width: 40rem;
195 | margin: 0 auto;
196 | padding: 5rem 4rem;
197 |
198 | display: flex;
199 |
200 | svg {
201 | height: 3rem;
202 | width: 3rem;
203 | fill: $color-primary;
204 | transform: translateY(-0.3rem);
205 | }
206 |
207 | p {
208 | margin-left: 1.5rem;
209 | font-size: 1.8rem;
210 | line-height: 1.5;
211 | font-weight: 600;
212 | }
213 | }
214 |
--------------------------------------------------------------------------------
/18-forkify/starter/src/sass/_header.scss:
--------------------------------------------------------------------------------
1 | .header {
2 | grid-area: head;
3 | background-color: $color-grey-light-1;
4 | display: flex;
5 | align-items: center;
6 | justify-content: space-between;
7 |
8 | &__logo {
9 | margin-left: 4rem;
10 | height: 4.6rem;
11 | display: block;
12 | }
13 | }
14 |
15 | .search {
16 | background-color: #fff;
17 | border-radius: 10rem;
18 | display: flex;
19 | align-items: center;
20 | padding-left: 3rem;
21 | transition: all 0.3s;
22 |
23 | &:focus-within {
24 | transform: translateY(-2px);
25 | box-shadow: 0 0.7rem 3rem rgba($color-grey-dark-1, 0.08);
26 | }
27 |
28 | &__field {
29 | border: none;
30 | background: none;
31 | font-family: inherit;
32 | color: inherit;
33 | font-size: 1.7rem;
34 | width: 30rem;
35 |
36 | &:focus {
37 | outline: none;
38 | }
39 |
40 | &::placeholder {
41 | color: $color-grey-light-3;
42 | }
43 |
44 | @media only screen and (max-width: $bp-medium) {
45 | width: auto;
46 |
47 | &::placeholder {
48 | color: white;
49 | }
50 | }
51 | }
52 |
53 | &__btn {
54 | font-weight: 600;
55 | font-family: inherit;
56 | }
57 | }
58 |
59 | .nav {
60 | align-self: stretch;
61 | margin-right: 2.5rem;
62 |
63 | &__list {
64 | list-style: none;
65 | display: flex;
66 | height: 100%;
67 | }
68 |
69 | &__item {
70 | position: relative;
71 | }
72 |
73 | &__btn {
74 | height: 100%;
75 | font-family: inherit;
76 | color: inherit;
77 | font-size: 1.4rem;
78 | font-weight: 700;
79 | text-transform: uppercase;
80 | background: none;
81 | border: none;
82 | cursor: pointer;
83 | padding: 0 1.5rem;
84 | transition: all 0.3s;
85 |
86 | display: flex;
87 | align-items: center;
88 |
89 | svg {
90 | height: 2.4rem;
91 | width: 2.4rem;
92 | fill: $color-primary;
93 | margin-right: 0.7rem;
94 | transform: translateY(-1px);
95 | }
96 |
97 | &:focus {
98 | outline: none;
99 | }
100 |
101 | &:hover {
102 | background-color: $color-grey-light-2;
103 | }
104 | }
105 | }
106 |
107 | .bookmarks {
108 | padding: 1rem 0;
109 | position: absolute;
110 | // right: 0;
111 | right: -2.5rem;
112 | z-index: 10;
113 | width: 40rem;
114 | background-color: #fff;
115 | box-shadow: 0 0.8rem 5rem 2rem rgba($color-grey-dark-1, 0.1);
116 |
117 | visibility: hidden;
118 | opacity: 0;
119 | transition: all 0.5s 0.2s;
120 |
121 | &__list {
122 | list-style: none;
123 | }
124 |
125 | &__field {
126 | cursor: pointer;
127 | padding: 0 4rem;
128 |
129 | display: flex;
130 | align-items: center;
131 | height: 100%;
132 | transition: all 0.3s;
133 |
134 | &:hover {
135 | background-color: $color-grey-light-2;
136 | }
137 | }
138 |
139 | &:hover,
140 | .nav__btn--bookmarks:hover + & {
141 | visibility: visible;
142 | opacity: 1;
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/18-forkify/starter/src/sass/_preview.scss:
--------------------------------------------------------------------------------
1 | .preview {
2 | &__link {
3 | &:link,
4 | &:visited {
5 | display: flex;
6 | align-items: center;
7 | padding: 1.5rem 3.25rem;
8 | transition: all 0.3s;
9 | border-right: 1px solid #fff;
10 | text-decoration: none;
11 | }
12 |
13 | &:hover {
14 | background-color: $color-grey-light-1;
15 | transform: translateY(-2px);
16 | }
17 |
18 | &--active {
19 | background-color: $color-grey-light-1;
20 | }
21 | }
22 |
23 | &__fig {
24 | flex: 0 0 5.8rem;
25 | border-radius: 50%;
26 | overflow: hidden;
27 | height: 5.8rem;
28 | margin-right: 2rem;
29 | position: relative;
30 | backface-visibility: hidden;
31 |
32 | &::before {
33 | content: '';
34 | display: block;
35 | height: 100%;
36 | width: 100%;
37 | position: absolute;
38 | top: 0;
39 | left: 0;
40 | background-image: linear-gradient(
41 | to right bottom,
42 | $color-grad-1,
43 | $color-grad-2
44 | );
45 | opacity: 0.4;
46 | }
47 |
48 | img {
49 | display: block;
50 | width: 100%;
51 | height: 100%;
52 | object-fit: cover;
53 | transition: all 0.3s;
54 | }
55 | }
56 |
57 | &__data {
58 | display: grid;
59 | width: 100%;
60 | grid-template-columns: 1fr 2rem;
61 | row-gap: 0.1rem;
62 | align-items: center;
63 | }
64 |
65 | &__title {
66 | grid-column: 1/-1;
67 | font-size: 1.45rem;
68 | color: $color-primary;
69 | text-transform: uppercase;
70 | font-weight: 600;
71 |
72 | // This is how text is truncated!
73 | text-overflow: ellipsis;
74 | max-width: 25rem;
75 | white-space: nowrap;
76 | overflow: hidden;
77 | }
78 |
79 | &__publisher {
80 | font-size: 1.15rem;
81 | color: $color-grey-dark-2;
82 | text-transform: uppercase;
83 | font-weight: 600;
84 | }
85 |
86 | &__user-generated {
87 | background-color: darken($color-grey-light-2, 2%);
88 |
89 | display: flex;
90 | align-items: center;
91 | justify-content: center;
92 | height: 2rem;
93 | width: 2rem;
94 | border-radius: 10rem;
95 |
96 | margin-left: auto;
97 | margin-right: 1.75rem;
98 |
99 | svg {
100 | height: 1.2rem;
101 | width: 1.2rem;
102 | fill: $color-primary;
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/18-forkify/starter/src/sass/_recipe.scss:
--------------------------------------------------------------------------------
1 | .recipe {
2 | background-color: $color-grey-light-1;
3 |
4 | ///////////
5 | // FIGURE
6 | &__fig {
7 | height: 32rem;
8 | position: relative;
9 | // transform: scale(1.04) translateY(-1px);
10 | transform-origin: top;
11 |
12 | &::before {
13 | content: '';
14 | display: block;
15 | height: 100%;
16 | width: 100%;
17 | position: absolute;
18 | top: 0;
19 | left: 0;
20 | background-image: linear-gradient(
21 | to right bottom,
22 | $color-grad-1,
23 | $color-grad-2
24 | );
25 | opacity: 0.6;
26 | }
27 | }
28 |
29 | &__img {
30 | width: 100%;
31 | display: block;
32 | height: 100%;
33 | object-fit: cover;
34 | }
35 |
36 | &__title {
37 | position: absolute;
38 | bottom: 0;
39 | left: 50%;
40 | transform: translate(-50%, 20%) skewY(-6deg);
41 | color: #fff;
42 | font-weight: 700;
43 | font-size: 3.25rem;
44 | text-transform: uppercase;
45 | width: 50%;
46 | line-height: 1.95;
47 | text-align: center;
48 |
49 | span {
50 | -webkit-box-decoration-break: clone;
51 | box-decoration-break: clone;
52 | padding: 1.3rem 2rem;
53 | background-image: linear-gradient(
54 | to right bottom,
55 | $color-grad-1,
56 | $color-grad-2
57 | );
58 | }
59 |
60 | @media only screen and (max-width: $bp-medium) {
61 | width: 70%;
62 | }
63 | }
64 |
65 | ///////////
66 | // DETAILS
67 | &__details {
68 | display: flex;
69 | align-items: center;
70 | padding: 7.5rem 8rem 3.5rem 8rem;
71 | }
72 |
73 | &__info {
74 | font-size: 1.65rem;
75 | text-transform: uppercase;
76 | display: flex;
77 | align-items: center;
78 |
79 | &:not(:last-child) {
80 | margin-right: 4.5rem;
81 | }
82 | }
83 |
84 | &__info-icon {
85 | height: 2.35rem;
86 | width: 2.35rem;
87 | fill: $color-primary;
88 | margin-right: 1.15rem;
89 | }
90 |
91 | &__info-data {
92 | margin-right: 0.5rem;
93 | font-weight: 700;
94 | }
95 |
96 | &__info-buttons {
97 | display: flex;
98 | margin-left: 1.6rem;
99 | transform: translateY(-1px);
100 | }
101 |
102 | &__user-generated {
103 | background-color: darken($color-grey-light-2, 2%);
104 |
105 | display: flex;
106 | align-items: center;
107 | justify-content: center;
108 | height: 4rem;
109 | width: 4rem;
110 | border-radius: 10rem;
111 |
112 | margin-left: auto;
113 | margin-right: 1.75rem;
114 |
115 | svg {
116 | height: 2.25rem;
117 | width: 2.25rem;
118 | fill: $color-primary;
119 | }
120 | }
121 |
122 | ///////////
123 | // INGREDIENTS
124 | &__ingredients {
125 | padding: 5rem 8rem;
126 | font-size: 1.6rem;
127 | line-height: 1.4;
128 | background-color: $color-grey-light-2;
129 | display: flex;
130 | flex-direction: column;
131 | align-items: center;
132 | }
133 |
134 | &__ingredient-list {
135 | display: grid;
136 | grid-template-columns: 1fr 1fr;
137 | gap: 2.5rem 3rem;
138 | list-style: none;
139 | }
140 |
141 | &__ingredient {
142 | display: flex;
143 | }
144 |
145 | &__icon {
146 | height: 2rem;
147 | width: 2rem;
148 | fill: $color-primary;
149 | margin-right: 1.1rem;
150 | flex: 0 0 auto;
151 | margin-top: 0.1rem;
152 | }
153 |
154 | &__quantity {
155 | margin-right: 0.5rem;
156 | flex: 0 0 auto;
157 | }
158 |
159 | ///////////
160 | // DIRECTIONS
161 | &__directions {
162 | padding: 5rem 10rem;
163 | padding-bottom: 5rem;
164 | display: flex;
165 | flex-direction: column;
166 | align-items: center;
167 | }
168 |
169 | &__directions-text {
170 | font-size: 1.7rem;
171 | text-align: center;
172 | margin-bottom: 3.5rem;
173 | color: $color-grey-dark-2;
174 | }
175 |
176 | &__publisher {
177 | font-weight: 700;
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/18-forkify/starter/src/sass/_searchResults.scss:
--------------------------------------------------------------------------------
1 | .search-results {
2 | padding: 3rem 0;
3 | display: flex;
4 | flex-direction: column;
5 | }
6 |
7 | .results {
8 | list-style: none;
9 | margin-bottom: 2rem;
10 | }
11 |
12 | .pagination {
13 | margin-top: auto;
14 | padding: 0 3.5rem;
15 |
16 | &::after {
17 | content: '';
18 | display: table;
19 | clear: both;
20 | }
21 |
22 | &__btn {
23 | &--prev {
24 | float: left;
25 | }
26 | &--next {
27 | float: right;
28 | }
29 | }
30 | }
31 |
32 | .copyright {
33 | color: $color-grey-dark-2;
34 | font-size: 1.2rem;
35 | padding: 0 3.5rem;
36 | margin-top: 4rem;
37 |
38 | .twitter-link:link,
39 | .twitter-link:visited {
40 | color: $color-grey-dark-2;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/18-forkify/starter/src/sass/_upload.scss:
--------------------------------------------------------------------------------
1 | .add-recipe-window {
2 | position: fixed;
3 | top: 50%;
4 | left: 50%;
5 | transform: translate(-50%, -50%);
6 | width: 100rem;
7 | background-color: white;
8 | border-radius: 9px;
9 |
10 | padding: 5rem 6rem;
11 | box-shadow: 0 4rem 6rem rgba(0, 0, 0, 0.25);
12 | z-index: 1000;
13 | transition: all 0.5s;
14 |
15 | .btn--close-modal {
16 | font-family: inherit;
17 | color: inherit;
18 | position: absolute;
19 | top: 0.5rem;
20 | right: 1.6rem;
21 | font-size: 3.5rem;
22 | cursor: pointer;
23 | border: none;
24 | background: none;
25 | }
26 | }
27 |
28 | .overlay {
29 | position: fixed;
30 | top: 0;
31 | left: 0;
32 | width: 100%;
33 | height: 100%;
34 | background-color: rgba(0, 0, 0, 0.4);
35 | backdrop-filter: blur(4px);
36 | z-index: 100;
37 | transition: all 0.5s;
38 | }
39 |
40 | .hidden {
41 | visibility: hidden;
42 | opacity: 0;
43 | }
44 |
45 | .upload {
46 | display: grid;
47 | grid-template-columns: 1fr 1fr;
48 | gap: 4rem 6rem;
49 |
50 | &__column {
51 | display: grid;
52 | grid-template-columns: 1fr 2.8fr;
53 | align-items: center;
54 | gap: 1.5rem;
55 |
56 | & label {
57 | font-size: 1.5rem;
58 | font-weight: 600;
59 | color: inherit;
60 | }
61 |
62 | & input {
63 | font-size: 1.5rem;
64 | padding: 0.8rem 1rem;
65 | border: 1px solid #ddd;
66 | border-radius: 0.5rem;
67 | transition: all 0.2s;
68 |
69 | &::placeholder {
70 | color: $color-grey-light-3;
71 | }
72 |
73 | &:focus {
74 | outline: none;
75 | border: 1px solid $color-primary;
76 | background-color: $color-grey-light-1;
77 | }
78 | }
79 |
80 | & button {
81 | grid-column: 1 / span 2;
82 | justify-self: center;
83 | margin-top: 1rem;
84 | }
85 | }
86 |
87 | &__heading {
88 | font-size: 2.25rem;
89 | font-weight: 700;
90 | text-transform: uppercase;
91 | margin-bottom: 1rem;
92 | grid-column: 1/-1;
93 | }
94 |
95 | &__btn {
96 | grid-column: 1 / -1;
97 | justify-self: center;
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/18-forkify/starter/src/sass/main.scss:
--------------------------------------------------------------------------------
1 | @import 'base';
2 | @import 'components';
3 | @import 'header';
4 | @import 'preview';
5 | @import 'searchResults';
6 | @import 'recipe';
7 | @import 'upload';
8 |
--------------------------------------------------------------------------------