├── images ├── protochain.png ├── cantransition.png ├── domscreenshot.png └── diagramforproto.png ├── README.md ├── LICENSE ├── advanced theory ├── authentication.md ├── APIs in JS.md ├── ES2016 and 2017.md ├── advanced array methods.md ├── AJAX.md ├── css3.md ├── testing.md ├── asynchronous JS.md └── OOP with JS.md └── basic theory ├── js and html.md └── basic JS info.md /images/protochain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/V1raNi/webdev-bootcamp-theory/HEAD/images/protochain.png -------------------------------------------------------------------------------- /images/cantransition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/V1raNi/webdev-bootcamp-theory/HEAD/images/cantransition.png -------------------------------------------------------------------------------- /images/domscreenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/V1raNi/webdev-bootcamp-theory/HEAD/images/domscreenshot.png -------------------------------------------------------------------------------- /images/diagramforproto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/V1raNi/webdev-bootcamp-theory/HEAD/images/diagramforproto.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Web Developer Bootcamp Theory 2 | 3 | This repository contains my notes which were taken during https://www.udemy.com/the-web-developer-bootcamp and https://www.udemy.com/the-advanced-web-developer-bootcamp 4 | 5 | The notes contain some basic and (a little) advanced information about JavaScript, CSS, React and Redux along with my comments. I tried to write everything in the way a novice learner (such as myself) would understand. 6 | 7 | Please bear in mind that the notes here do not cover everything, are not 100% complete, and are written based on the information from Udemy courses. So if you need something more comprehensive, please see other documentation online (MDN, W3, etc). 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Dmitry Shamshurin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /advanced theory/authentication.md: -------------------------------------------------------------------------------- 1 | # Authentication 2 | 3 | #### Table of Contents 4 | 5 | - [Authentication](#authentication) 6 | - [Table of Contents](#table-of-contents) 7 | - [One Way Hashing](#one-way-hashing) 8 | - [Example of Hashing](#example-of-hashing) 9 | - [Sign In (Authentication)](#sign-in-authentication) 10 | - [JWT (JSON Web Token)](#jwt-json-web-token) 11 | - [Authentication](#authentication-1) 12 | - [Sending JWT to Server](#sending-jwt-to-server) 13 | 14 | ## One Way Hashing 15 | 16 | It's converting data into a fixed length has string; we can only recreate the hash if we know the original data 17 | 18 | Once we have the has, we can't go back and figure out what the original data was 19 | 20 | It's applicable for saving passwords on our server - we never save actual password; the data that the site saves should be just hash and nothing else 21 | 22 | #### Example of Hashing 23 | 24 | Password 'password' -> given to a hash library 'bcrypt' -> $2a$10$9Mconplm8A780pY6iB2q.eBwkdldFbnz2tSH2uqHEi5B9KTpR3O8. 25 | 26 | ### Sign In (Authentication) 27 | 28 | Once we've saved that password as a has, the process of signing is like this: 29 | 30 | $2a$10$9Mconplm8A780pY6iB2q.eBwkdldFbnz2tSH2uqHEi5B9KTpR3O8. (in database) -> user provides a password ('password') -> password goes through 'bcrypt' -> hash is generated again -> compare those hashes -> log in 31 | 32 | ### JWT (JSON Web Token) 33 | 34 | jwt.io 35 | 36 | Users don't want to enter their passwords on every page; we need some proof that we have logged in in the past 37 | 38 | We can use JWTs as proof that we've logged in before - JWT is a web standard for storing signed data (sometimes called 'jot') 39 | 40 | JWT Format: 41 | 42 | ``` 43 | Header: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. 44 | Payload: eyJ1c2VySWQiOiIxMjM0In0. 45 | Signature: kud-czcx6yOSSQgB0lKbibHNFmlAJwrV8iRQ1Ha-r-Q 46 | ``` 47 | 48 | Signature is used to make sure that the header and the payload has not been tempered with; both the header and the payload, and then also a secret key are inputs to generate the signature 49 | - A secret key is a string that we store on the server but we don't give people access to it (use env variables, install dotenv for connecting to .env file) 50 | 51 | The server is the one that keeps track of that secret key, and only it can know about the secret 52 | - If a hacker were to get access to that key then the hacker could also make fake JWTs with whatever header and payload that they want 53 | - So the thing that keeps this secure is the fact that this signature generation can only be done by the server, it can't be done by the client of by anyone else 54 | 55 | #### Authentication 56 | 57 | The server verifies the payload and the header to make sure it hasn't been tempered with, and if it hasn't, it looks in the payload to see that it has something like a user ID stored, and then if that user ID is there, that verifies that we've logged in in the past 58 | 59 | When the user signs in, we give the generated JWT back to the client; every authenticated request after that the client needs to send us the JWT back (if we're the server) 60 | - As long as the client sends a JWT for which that signature matches the signature that we generate on the server, we are authenticated 61 | - Once we look in this payload, we can see what the user ID is to figure out which user is authenticated 62 | - If something is changed (header, payload, signature) it will lead to an invalid signature problem 63 | - If the header or payload are different, since they are inputs to generate signature, it will result in the server trying to generate a different signature 64 | 65 | #### Sending JWT to Server 66 | 67 | The standard way to send the JWT is to include the JWT in the authorization header, and the first part of this header is typically 'Bearer' (type portion of authorization) 68 | 69 | HTTP Header: Authorization: Bearer \ (e.g. Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjM0In0.kud-czcx6yOSSQgB0lKbibHNFmlAJwrV8iRQ1Ha-r-Q) -------------------------------------------------------------------------------- /advanced theory/APIs in JS.md: -------------------------------------------------------------------------------- 1 | # JSON API with JS 2 | 3 | This section mostly requires information which is in JS backend doc 4 | 5 | The main difference is that we don't load new pages, we are sending and receiving requests with data 6 | 7 | #### Table of Contents 8 | 9 | - [JSON API with JS](#json-api-with-js) 10 | - [Table of Contents](#table-of-contents) 11 | - [Endpoints](#endpoints) 12 | - [Responding with JSON](#responding-with-json) 13 | - [Routes](#routes) 14 | - [Index](#index) 15 | - [Create](#create) 16 | - [Show](#show) 17 | - [Update](#update) 18 | - [Delete](#delete) 19 | - [Helpers](#helpers) 20 | - [Serving a Static File](#serving-a-static-file) 21 | 22 | ## Endpoints 23 | 24 | Endpoints are basically routes 25 | 26 | Example with a todo app (RESTful): 27 | 28 | ``` 29 | Verb Route Description 30 | GET /api/todos List all todos 31 | POST /api/todos Create a new todo 32 | GET /api/todos/:todoId Retrieve a todo 33 | PUT /api/todos/:todoId Update a todo 34 | DELETE /api/todos/:todoId Delete a todo 35 | ``` 36 | 37 | ## Responding with JSON 38 | 39 | res.send is dynamic, depending on the contents of what we send: if we pass string, it will render html, but if we pass JS object, it will be treated as JSON 40 | 41 | ```javascript 42 | app.get('/', function(req, res) { 43 | res.send({message: 'Hi there from JS object'}); // it will convert to a string, and send as JSON 44 | // if we pass a string, it will be treated as a string 45 | res.send('{data: 12345}'); 46 | }); 47 | ``` 48 | 49 | Also there is res.json method which does the same thing because in res.send source code it actually calls res.json (send is sort of parent) 50 | 51 | ```javascript 52 | app.get('/', function(req, res) { 53 | res.json({message: 'Hi there from JS object'}); 54 | res.json('{data: 12345}'); // it will treat this string as a JSON 55 | }); 56 | ``` 57 | 58 | ## Routes 59 | 60 | We are assuming that we have this in our index.js file: 61 | 62 | ```javascript 63 | var todoRoutes = require('./routes/todos'); 64 | app.use('/api/todos', todoRoutes); 65 | ``` 66 | 67 | Schema for examples: 68 | 69 | ```javascript 70 | var mongoose = require('mongoose'); 71 | 72 | var todoSchema = new mongoose.Schema({ 73 | name: { 74 | type: String, 75 | required: 'Name cannot be blank!' 76 | }, 77 | completed: { 78 | type: Boolean, 79 | default: false 80 | }, 81 | created_date: { 82 | type: Date, 83 | default: Date.now 84 | } 85 | }); 86 | 87 | var Todo = mongoose.model('Todo', todoSchema); 88 | 89 | module.exports = Todo; 90 | ``` 91 | 92 | ### Index 93 | 94 | ```javascript 95 | // index route 96 | router.get('/', function(req, res) { 97 | db.Todo.find() 98 | .then(function(todos) { 99 | res.json(todos); 100 | }) 101 | .catch(function(err) { 102 | res.send(err); 103 | }); 104 | }); 105 | ``` 106 | 107 | ### Create 108 | 109 | ```javascript 110 | // create route 111 | router.post('/', function(req, res) { 112 | db.Todo.create(req.body) 113 | .then(function(newTodo) { 114 | // standard way to respond is res.send it back since it's importand to know that it worked, and date, the status abd the ID are going to be generated by mongo, so we want those to come back 115 | // we're also sending a different status code to be more explicit (201 - created) 116 | res.status(201).json(newTodo); 117 | }) 118 | .catch(function(err) { 119 | res.send(err); 120 | }) 121 | }); 122 | 123 | // if we try to send along some other data (like mood which is not in our schema), it doesn't actually try and insert that because that's not a part of our schema, so mongo doesn't care about that (our only defined key is name in this example) 124 | ``` 125 | 126 | ### Show 127 | 128 | ```javascript 129 | router.get('/:todoId', function(req, res) { 130 | db.Todo.findById(req.params.todoId) 131 | .then(function(foundTodo) { 132 | res.json(foundTodo); 133 | }) 134 | .catch(function(err) { 135 | res.send(err); 136 | }) 137 | }); 138 | ``` 139 | 140 | ## Update 141 | 142 | ```javascript 143 | router.put('/:todoId', function(req, res) { 144 | db.Todo.findOneAndUpdate({_id: req.params.todoId}, req.body, {new: true}) 145 | .then(function(todo) { 146 | res.json(todo); // by default it responds with old data, before it was updated that's why we need {new: true} 147 | }) 148 | .catch(function(err) { 149 | res.send(err); 150 | }) 151 | }); 152 | 153 | module.exports = router; 154 | ``` 155 | 156 | ## Delete 157 | 158 | ```javascript 159 | router.delete('/:todoId', function(req, res) { 160 | db.Todo.remove({_id: req.params.todoId}) 161 | .then(function() { 162 | res.json({message: 'We deleted it'}); 163 | }) 164 | .catch(function(err) { 165 | res.send(err); 166 | }); 167 | }); 168 | ``` 169 | 170 | ## Helpers 171 | 172 | We can refactor routes file by moving all the logic inside our route handlers into a separate helper so that our routes will be really simple 173 | - Look up controllers in MVC framework 174 | - Are helper files the same as Controller files in the MVC framework? 175 | - I’d consider the handlers/routesto be more controllers 176 | - MAYBE not true: controller is mainly for processing logic and bringing together database and templates whereas helper is mainly used for shared codes like dates 177 | - Helpers are either in a helpers folder (helpers/todos.js) or named (todos_helper.js) 178 | 179 | Exports 180 | - Exports isn't exactly an alias for module.exports. exports.a = function b(){} means that module.exports.a is a function, but setting module.exports = function b(){} can not be done with just exports. If you want to do a "default" export and only export out a single thing, you have to use module.exports 181 | 182 | Routes file: 183 | 184 | ```javascript 185 | var express = require('express'), 186 | router = express.Router(), 187 | helpers = require('../helpers/todos'); 188 | 189 | 190 | // index and post routes 191 | router.route('/') 192 | .get(helpers.getTodos) 193 | .post(helpers.createTodo); 194 | 195 | // show, update, and delete 196 | router.route('/:todoId') 197 | .get(helpers.getTodo) 198 | .put(helpers.updateTodo) 199 | .delete(helpers.deleteTodo); 200 | 201 | module.exports = router; 202 | ``` 203 | 204 | Helpers file: 205 | 206 | ```javascript 207 | var db = require('../models'); 208 | 209 | // exports object is initialized by node 210 | 211 | exports.getTodos = function(req, res) { 212 | db.Todo.find() 213 | .then(function(todos) { 214 | res.json(todos); 215 | }) 216 | .catch(function(err) { 217 | res.send(err); 218 | }); 219 | } 220 | 221 | exports.createTodo = function(req, res) { 222 | console.log(req.body); 223 | db.Todo.create(req.body) 224 | .then(function(newTodo) { 225 | 226 | res.status(201).json(newTodo); 227 | }) 228 | .catch(function(err) { 229 | res.send(err); 230 | }) 231 | } 232 | 233 | exports.getTodo = function(req, res) { 234 | db.Todo.findById(req.params.todoId) 235 | .then(function(foundTodo) { 236 | res.json(foundTodo); 237 | }) 238 | .catch(function(err) { 239 | res.send(err); 240 | }) 241 | } 242 | 243 | exports.updateTodo = function(req, res) { 244 | db.Todo.findOneAndUpdate({_id: req.params.todoId}, req.body, {new: true}) 245 | .then(function(todo) { 246 | res.json(todo); // by default it responds with old data, before it was updated that's why we need {new: true} 247 | }) 248 | .catch(function(err) { 249 | res.send(err); 250 | }) 251 | } 252 | 253 | exports.deleteTodo = function(req, res) { 254 | db.Todo.remove({_id: req.params.todoId}) 255 | .then(function() { 256 | res.json({message: 'We deleted it'}); 257 | }) 258 | .catch(function(err) { 259 | res.send(err); 260 | }); 261 | } 262 | 263 | module.exports = exports; 264 | ``` 265 | 266 | ## Serving a Static File 267 | 268 | We can serve static files with res.sendFile 269 | 270 | ```javascript 271 | app.use(express.static(__dirname + '/public')); 272 | app.use(express.static(__dirname + '/views')); 273 | 274 | app.get('/', function(req, res) { 275 | res.sendFile('index.html'); 276 | }); 277 | ``` -------------------------------------------------------------------------------- /advanced theory/ES2016 and 2017.md: -------------------------------------------------------------------------------- 1 | # ES 2016 and 2017 2 | 3 | #### Table of Contents 4 | 5 | - [ES 2016 and 2017](#es-2016-and-2017) 6 | - [Table of Contents](#table-of-contents) 7 | - [ES 2016](#es-2016) 8 | - [Exponentiation Operator](#exponentiation-operator) 9 | - [includes](#includes) 10 | - [ES 2017](#es-2017) 11 | - [padStart](#padstart) 12 | - [padEnd](#padend) 13 | - [Async Functions](#async-functions) 14 | - [Await](#await) 15 | - [Object async](#object-async) 16 | - [Class async](#class-async) 17 | - [Error Handling](#error-handling) 18 | - [HTTP Requests with async](#http-requests-with-async) 19 | - [await with Promise.all](#await-with-promiseall) 20 | - [Object Rest and Spread](#object-rest-and-spread) 21 | - [Object Rest](#object-rest) 22 | - [Object Spread](#object-spread) 23 | 24 | ## ES 2016 25 | 26 | ### Exponentiation Operator 27 | 28 | There exists a parameter to figure out value of one number to the power of another 29 | 30 | ```javascript 31 | // ES2015 32 | var calculatedNumber = Math.pow(2, 4); 33 | 34 | caltulatedNumber; // 16 35 | 36 | // ES2016 37 | var calculatedNumber = 2 ** 4; 38 | 39 | calculatedNumber; // 16 40 | 41 | // ES2015 42 | var nums = [1, 2, 3, 4]; 43 | var total = 2; 44 | 45 | for (let i = 0; i < nums.length; i++) { 46 | total Math.pow(total, nums[i]); 47 | } 48 | 49 | // ES2016 50 | var nums = [1, 2, 3, 4]; 51 | var total = 2; 52 | 53 | for (let i = 0; i < nums.length; i++) { 54 | total total **= nums[i]; 55 | } 56 | ``` 57 | 58 | ### includes 59 | 60 | In ES2015 we saw that strings have .includes which returns true if the value passed to it is included in the string 61 | 62 | In ES2016 arrays now have .includes as well, which is a good replacement for using indexOf to check if the value exists inside of an array 63 | 64 | ```javascript 65 | // ES2015 66 | var nums = [1, 2, 3, 4, 5]; 67 | nums.indexOf(3) > -1; // true 68 | nums.indexOf(44) > -1; // false 69 | 70 | // ES2016 71 | var nums = [1, 2, 3, 4, 5]; 72 | nums.includes(3); // true 73 | nums.includes(44); // false 74 | ``` 75 | 76 | ## ES 2017 77 | 78 | ### padStart 79 | 80 | Allows us to pad (to place) a certain character number of times before the start of a string 81 | - The first parameter is the totale length of the new string 82 | - The second parameter is what to pad with from the start; the default is an empty space 83 | 84 | This is useful when we need to have strings that are all the same length but our input might now always have that. so maybe we want to pad some input with zeros or some other operator 85 | 86 | ```javascript 87 | 'awesome'.padStart(10); // ' awesome' 88 | 'awesome'.padStart(10, '!'); // '!!!awesome' 89 | ``` 90 | 91 | ### padEnd 92 | 93 | The same as padStart, but places characters to the end of a string 94 | 95 | ```javascript 96 | 'awesome'.padEnd(10, '!'); // 'awesome!!!' 97 | ``` 98 | 99 | ### Async Functions 100 | 101 | A special kind of function that is created using the word 'async' 102 | 103 | The purpose of async functions is to simplify writing asynchronous code, specifically Promises 104 | 105 | When the async function is invoked, a promise is returned to us and will resolve with whatever value is returned from the function 106 | 107 | ```javascript 108 | async function first() { 109 | return 'We did it!'; 110 | } 111 | 112 | first(); // returns a promise 113 | first().then(val => console.log(val)); // 'We did it!' 114 | ``` 115 | 116 | What makes them really special is the 'await' keyword 117 | 118 | #### Await 119 | 120 | A reserved keyword that can only be used inside of async functions 121 | 122 | Await pauses the execution of the async function and is followed by a Promise; the 'await' keyword waits for the promise to resolve, and then resumes the async function's execution and returnes the resolved value (like a pause button) 123 | 124 | Await allows us to write async code that reads like it's sync (we can remove the hassle of nested callbacks, promise chains or multiple yield statements and generator functions) 125 | 126 | ```javascript 127 | async function getMovieData() { 128 | console.log('starting!'); 129 | var movieData = await $.getJSON('https://omdbapi.com?t=titanic&apikey=thewdb'); 130 | // this line does NOT run until the promise (await) is resolved! 131 | console.log('all done!'); 132 | console.log(movieData); 133 | } 134 | 135 | getMovieData(); // logs an object with data about the movie 136 | // we don't need .then or callback, or yield 137 | ``` 138 | 139 | #### Object async 140 | 141 | We can also place async functions as methods inside objects by prefixing the method with the word async and using ES 2015 object method notation to write the function 142 | 143 | ```javascript 144 | var movieCollector = { 145 | data: 'titanic', 146 | async getMovie() { 147 | var response = await $.getJSON(`https://omdbapi.com?t=${this.data}&apikey=thewdb`); 148 | console.log(response); 149 | } 150 | } 151 | 152 | movieCollector.getMovie(); 153 | ``` 154 | 155 | #### Class async 156 | 157 | We can also place async functions as instance methods with ES2015 class syntax 158 | 159 | ```javascript 160 | class MovieData { 161 | constructor(name) { 162 | this.name = name; 163 | } 164 | async getMovie() { 165 | var response = await $.getJSON(`https://omdbapi.com?t=${this.name}&apikey=thewdb`); 166 | console.log(response); 167 | } 168 | } 169 | 170 | var m = new MovieData('shrek'); 171 | m.getMovie(); 172 | ``` 173 | 174 | This seems great, but we're making a dangerous assumption - that our promises will be resolved successfully 175 | 176 | #### Error Handling 177 | 178 | If a promise is rejected using await, JS will throw an error, so we can easily use a try/catch statement inside of the try block to handle errors 179 | 180 | ```javascript 181 | async function getUser(user) { 182 | try { 183 | var response = await $.getJSON(`https://api.github.com/users/${user}`); 184 | console.log(response.name); 185 | } catch(e) { 186 | console.log('User does not exist!'); 187 | } 188 | } 189 | 190 | getUser('elie'); // Elie Schoppik 191 | getUser('asdasdasd'); // User does not exist! 192 | ``` 193 | 194 | #### HTTP Requests with async 195 | 196 | ```javascript 197 | // two requests are made sequentially, not parallelly 198 | async function getMovieData() { 199 | var responseOne = await $.getJSON('https://omdbapi.com?t=titanic&apikey=thewdb'); 200 | // this response two will not begin until the entire responseOne is resolved 201 | // imagine if it takes several seconds, our app would slow down 202 | var responseTwo = await $.getJSON('https://omdbapi.com?t=shrek&apikey=thewdb'); 203 | console.log(responseOne); 204 | console.log(responseTwo); 205 | } 206 | 207 | getMovieData(); 208 | ``` 209 | 210 | We can avoid this by returning the promises right away and make HTTP requests in parallel, and then 'await' their resolved promise 211 | 212 | ```javascript 213 | async function getMovieData() { 214 | var titanicPromise = $.getJSON('https://omdbapi.com?t=titanic&apikey=thewdb'); 215 | var shrekPromise = $.getJSON('https://omdbapi.com?t=shrek&apikey=thewdb'); 216 | 217 | var titanicData = await titanicPromise; 218 | var shrekData = await shrekPromise; 219 | 220 | console.log(titanicData); 221 | console.log(shrekData); 222 | } 223 | 224 | getMovieData(); 225 | ``` 226 | 227 | #### await with Promise.all 228 | 229 | We can use Promise.all to await multiple resolved promises 230 | 231 | ```javascript 232 | // we're waiting for an array of promises to resolve using the 'await' and Promise.all 233 | // Promise.all accepts an array of promises, and returns a promise which when resolved returns an array of resolved values 234 | // instead of .then and a callback, we can simply await the resolution of promise.all and then access those values in our moviesList array 235 | async function getMovieData(first, second) { 236 | var moviesList = await Promise.all([ 237 | $.getJSON(`https://omdbapi.com?t=${first}&apikey=thewdb`); 238 | $.getJSON(`https://omdbapi.com?t=${second}&apikey=thewdb`); 239 | ]); 240 | console.log(moviesList[0].Year); 241 | console.log(moviesList[1].Year); 242 | } 243 | 244 | getMovieData('shrek', 'blade'); 245 | 246 | // 2001 247 | // 1998 248 | ``` 249 | 250 | ### Object Rest and Spread 251 | 252 | ES2015 provided the rest and spread operator for arrays 253 | - The rest operator was used as a parameter to functions and gathered the remaining arguments as an array 254 | - The spread operator was useful for spreading out values in an array as comma separated values 255 | 256 | #### Object Rest 257 | 258 | Gather remaining (rest) of keys and values in an object, and create a new one out of them 259 | 260 | ```javascript 261 | var instructor = {first: 'Elie', last: 'Schoppik', job: 'instructor', numSiblings: 3}; 262 | 263 | // If we want to creates 'first' and 'last' variables, how can we collect the remaining keys and values? With rest operator 264 | var {first, last, ...data} = instructor; // destructuring the object 265 | first; // 'Elie' 266 | last; // 'Schoppik' 267 | data; // {job:'instructor', numSiblings:3} 268 | ``` 269 | 270 | #### Object Spread 271 | 272 | Spread out keys and values from one object to another 273 | 274 | Great for creating new objects starting with default values and is a more concise alternative to Object.assign (but similar to it) 275 | 276 | ```javascript 277 | var instructor = {first: 'Elie', last: 'Schoppik', job: 'instructor'}; 278 | 279 | // instructor2 will accept all of the keys and values of instructor and overwrite the first and last keys with 'Tim' and 'Garcia' 280 | var instructor2 = {...instructor, first:'Tim', last:'Garcia'}; 281 | 282 | var defaults = {job: 'instructor', ownsCat: true, ownsDog: true}; 283 | var matt = {...defaults, ownsCat: false}; 284 | var colt = {...defaults, ownsDog: false}; 285 | ``` -------------------------------------------------------------------------------- /advanced theory/advanced array methods.md: -------------------------------------------------------------------------------- 1 | # Advanced Array Methods 2 | 3 | #### Table of Contents 4 | 5 | - [Advanced Array Methods](#advanced-array-methods) 6 | - [Table of Contents](#table-of-contents) 7 | - [forEach](#foreach) 8 | - [map](#map) 9 | - [filter](#filter) 10 | - [some](#some) 11 | - [every](#every) 12 | - [reduce](#reduce) 13 | 14 | ## forEach 15 | 16 | - Iterates through an array 17 | - Runs a callback function on each value in the array 18 | - Returns 'undefined' ALWAYS when the loop ends (i.e. storing in a var or returning in a function won't work) 19 | 20 | ```javascript 21 | // array method callback each value&index entire 22 | // in the arr array 23 | [1, 2, 3].forEach(function(value, index, array) { 24 | // the callback will be executed 3 times since there are 3 values in the array 25 | // each time value and index are different 26 | // we can call parameters whatever we want 27 | // we don't always need all three parameters, but their order is important 28 | }); 29 | 30 | // implementation of forEach 31 | function forEach(array, callback) { 32 | for (var i = 0; i < array.length; i++) { 33 | callback(array[i], i, array); 34 | } 35 | } 36 | 37 | // using forEach 38 | function halfValues(arr) { 39 | var newArr = []; 40 | arr.forEach(function(val) { 41 | newArr.push(val / 2); 42 | }); 43 | return newArr; 44 | } 45 | 46 | halfValues[2, 4, 6]; // [1, 2, 3] 47 | ``` 48 | 49 | ## map 50 | 51 | Basically it is forEach which transforms an array into another array with different values but of the same length 52 | 53 | - creates a new array 54 | - iterates through an array 55 | - runs a callback function for each value in the array 56 | - adds the result of that callback function to the new array 57 | - returns the new array 58 | 59 | ```javascript 60 | var arr = [1, 2, 3]; 61 | 62 | arr.map(function(value, index, array) { 63 | return value * 2; // if no return, there is an array of undefined's 64 | }); 65 | 66 | // [2, 4, 6] 67 | 68 | // implementation 69 | function map(arr, callback) { 70 | var newArr = []; 71 | for (var i = 0; i < arr.length; i++) { 72 | newArr.push(callback(arr[i], i, arr)); 73 | } 74 | return newArr; 75 | } 76 | 77 | // usage 78 | // we could use forEach here, but map is a bit more friendly since it already returns a new array to us 79 | // forEach can be used if we want to overwrite values in an array or change something externally 80 | // when we would like a new array to be returned, especially one of the same length, map should always be used 81 | function tripleValues(arr) { 82 | return arr.map(function(value) { 83 | return value * 3; 84 | }); 85 | } 86 | 87 | tripleValues([1, 2, 3]); // [3, 6, 9] 88 | 89 | function onlyFirstName(arr) { 90 | return arr.map(function(val) { 91 | return val.first; 92 | }); 93 | } 94 | 95 | onlyFirstName([{first: 'Tim', last: 'Garcia'}, {first: 'Matt', last: 'Lane'}]); 96 | 97 | // ['Tim', 'Matt'] 98 | ``` 99 | 100 | ## filter 101 | 102 | .filter helps to return arrays of the same or smaller size 103 | 104 | - creates a new array 105 | - iterates through an array 106 | - runs a callback function on each value in the array 107 | - if the callback function returns trues, that value will be added to the new array 108 | - if the callback function returns false, that value will ve ignored from the new array 109 | - the result of the callback will ALWAYS be a boolean 110 | 111 | ```javascript 112 | var arr = [1, 2, 3]; 113 | 114 | arr.filter(function(value, index, array) { 115 | // no need for an if statement, just return an expression that evaluates to true or false 116 | return value > 2; 117 | }); 118 | 119 | // [3] 120 | 121 | var instructors = [ 122 | {name: 'Elie'}, 123 | {name: 'Tim'}, 124 | {name: 'Colt'}, 125 | {name: 'Matt'} 126 | ]; 127 | 128 | instructors.filter(function(value, index, array) { 129 | return value.name.length > 3; 130 | }); 131 | 132 | // [{name: 'Elie'}, {name: 'Colt'}, {name: 'Matt'}]; 133 | 134 | // implementation 135 | function filter(array, callback) { 136 | var newArr = []; 137 | for (var i = 0; i < array.length; i++) { 138 | if (callback(array[i], i, array)) { 139 | newArr.push(array[i])l 140 | } 141 | } 142 | return newArr; 143 | } 144 | 145 | // usage 146 | function onlyFourLetters(arr) { 147 | return arr.filter(function(value) { 148 | return value.length === 4; 149 | }); 150 | } 151 | 152 | onlyFourLetters(['Rusty', 'Matt', 'Moxie', 'Colt']); // ['Matt', 'Colt'] 153 | 154 | function divisibleByThree(arr) { 155 | return arr.filter(function(value) { 156 | return value % 3 === 0; 157 | }); 158 | } 159 | 160 | divisibleByThree([1, 2, 3, 4, 5, 6, 7, 8, 9]); // [3, 6, 9] 161 | ``` 162 | 163 | ## some 164 | 165 | - iterates through an array 166 | - runs a callback on each value in the array 167 | - if the callback returns true for at least one single value, return true 168 | - otherwise, return false 169 | - the result of the callback will ALWAYS be a boolean 170 | 171 | ```javascript 172 | var arr = [1, 2, 3]; 173 | 174 | arr.some(function(value, index, array) { 175 | return value < 2; 176 | }); 177 | 178 | // true 179 | 180 | arr.some(function(value, index, array) { 181 | return value > 4; 182 | }); 183 | 184 | // false 185 | 186 | // implementation 187 | function some(array, callback) { 188 | for (var i = 0; i < array.length; i++) { 189 | if (callback(array[i], i, array)) { 190 | return true; 191 | } 192 | } 193 | return false; 194 | } 195 | 196 | // usage 197 | function hasEvenNumber(arr) { 198 | return arr.some(function(value) { 199 | return value % 2 === 0; 200 | }); 201 | } 202 | 203 | hasEvenNumber([1, 2, 3, 4]); // true 204 | hasEvenNumber([1, 3, 5]); // false 205 | 206 | function hasComme(str) { 207 | return str.split('').some(function(value) { 208 | return value === ','; 209 | }); 210 | } 211 | 212 | hasComma('This is wonderful'); // false 213 | hasComma('This, is wonderful'); // true 214 | ``` 215 | 216 | ## every 217 | 218 | - iterates through an array 219 | - runs a callback on each value in the array 220 | - if the callback returns true for every single value, return false 221 | - otherwise, return true 222 | - the result of the callback will ALWAYS be a boolean 223 | 224 | ```javascript 225 | var arr = [-1, -2, -3]; 226 | 227 | arr.every(function(value, index, array) { 228 | return value < 0; 229 | }); 230 | 231 | // true 232 | 233 | var arr = [-1, 2, -3]; 234 | 235 | arr.every(function(value, index, array) { 236 | return value < 0; 237 | }); 238 | 239 | // false 240 | 241 | // implementation 242 | function every(array, callback) { 243 | for (var i = 0; i < array.length; i++) { 244 | if (callback(array[i], i, array) === false) { 245 | return false; 246 | } 247 | } 248 | return true; 249 | } 250 | 251 | // usage 252 | function allLowerCase(str) { 253 | return str.split('').every(function(value) { 254 | return value === value.toLowerCase(); 255 | }); 256 | } 257 | 258 | allLowerCase('this is really nice'); // true 259 | allLowerCase('this is Really nice'); // false 260 | 261 | function allArrays(arr) { 262 | return arr.every(Array.isArray); 263 | } 264 | 265 | allArrays([[1], [2], [3, 4]]); // true 266 | arrArrays([[1], [2], {}]); // false 267 | ``` 268 | 269 | ## reduce 270 | 271 | - accepts a callback and an optional second parameter 272 | - iterates through an array 273 | - runs a callback on each value in the array 274 | - the first parameter to the callback is either the first value in the array or the optional second parameter 275 | - the first parameter to the callback is often called 'accumulator' 276 | - the returned value from the callback becomes the new value of accumulator 277 | - whatever is returned from the callback function, becomes the new value of the accumulator 278 | 279 | ```javascript 280 | [1, 2, 3].reduce(function(accumulator, nextValue, index, array) { 281 | // [1, 2, 3] - array 282 | // reduce - method 283 | // function - callback 284 | // accumulator - first value in array or optional second parameter 285 | // second value in array or first, if optional second parameter is passed 286 | // index - each index in the array 287 | // array - the entire array 288 | 289 | // whatever is returned inside here, will be the value of accumulator in the next iteration 290 | }, optional second parameter) 291 | 292 | // example 293 | var arr = [1, 2, 3, 4, 5]; 294 | 295 | arr.reduce(function(accumulator, nextValue) { 296 | return accumulator + nextValue; 297 | }); 298 | 299 | // accumulator nextValue returned value 300 | // 1 2 3 301 | // 3 3 6 302 | // 6 4 10 303 | // 10 5 15 304 | 305 | // adding a second parameter 306 | var arr = [1, 2, 3, 4, 5]; 307 | 308 | arr.reduce(function(accumulator, nextValue) { 309 | return accumulator + nextValue; 310 | // not returning - undefined 311 | }, 10); 312 | 313 | // accumulator nextValue returned value 314 | // 10 1 11 315 | // 11 2 13 316 | // 13 3 16 317 | // 16 4 20 318 | // 20 5 25 319 | ``` 320 | 321 | Using reduce to return different data types 322 | 323 | ```javascript 324 | var names = ['Tim', 'Matt', 'Colt', 'Elie']; 325 | 326 | names.reduce(function(accumulator, nextValue){ 327 | return accumulator += ' ' + nextValue; 328 | }, 'The instructors are'); 329 | 330 | // accumulator nextValue returned value 331 | // The instructors are Tim The instructors are Tim 332 | // The instructors are Tim Matt The instructors are Tim Matt 333 | // ... 334 | // The instructors are Tim Matt Colt Elie 335 | 336 | var arr = [5, 4, 1, 4, 5]; 337 | 338 | arr.reduce(function(accumulator, nextValue) { 339 | if (nextValue in accumulator) { 340 | accumulator[nextValue]++; 341 | } else { 342 | accumulator[nextValue] = 1; 343 | } 344 | return accumulator; 345 | }, {}); 346 | 347 | // {5: 2, 4: 2, 1: 1} 348 | ``` 349 | 350 | Usage of reduce 351 | 352 | ```javascript 353 | function sumOddNumbers(arr) { 354 | return arr.reduce(function(accumulator, nextValue) { 355 | if (nextValue % 2 !== 0) { 356 | accumulator += nextValue; 357 | } 358 | return accumulator; 359 | }, 0); 360 | } 361 | 362 | sumOddNumbers([1, 2, 3, 4, 5]); // 9 363 | 364 | function createFullName(arr) { 365 | return arr.reduce(function(accumulator, nextValue) { 366 | accumulator.push(nextValue.first + ' ' + nextValue.last); 367 | return accumulator; 368 | }, []); 369 | } 370 | 371 | createFullName([{first: 'Colt', last: 'Steele'}, {first: 'Matt', last: 'Lane'}]); 372 | // ['Colt Steele', 'Matt Lane'] 373 | ``` -------------------------------------------------------------------------------- /advanced theory/AJAX.md: -------------------------------------------------------------------------------- 1 | # AJAX 2 | 3 | Asynchronous Javascript and XML 4 | 5 | #### Table of Contents 6 | 7 | - [AJAX](#ajax) 8 | - [Table of Contents](#table-of-contents) 9 | - [What Is AJAX](#what-is-ajax) 10 | - [XML and JSON](#xml-and-json) 11 | - [XML](#xml) 12 | - [JSON](#json) 13 | - [Requests](#requests) 14 | - [XMLHTTP Request (XHR)](#xmlhttp-request-xhr) 15 | - [Problems with XHR](#problems-with-xhr) 16 | - [Fetch](#fetch) 17 | - [Fetch Options](#fetch-options) 18 | - [Fetch Error Handling](#fetch-error-handling) 19 | - [Problem with Fetch](#problem-with-fetch) 20 | - [jQuery and Axios](#jquery-and-axios) 21 | - [jQuery](#jquery) 22 | - [$.ajax](#ajax) 23 | - [$.get](#get) 24 | - [$.post](#post) 25 | - [$.json](#json) 26 | - [Axios](#axios) 27 | - [Axios Error Handling](#axios-error-handling) 28 | 29 | ## What Is AJAX 30 | 31 | AJAX is not: 32 | - A library 33 | - A framework 34 | - A technology 35 | 36 | AJAX is an approach to webdev, a concept, a way of structuring apps 37 | 38 | It appeared it 2005 as a way to combine HTML, CSS, JS, DOM, XMLHTTP Requests and create apps that can update without refreshing 39 | 40 | With AJAX, websites can send and request data from a server in the background without disturbing the current page (led to today's single page apps with features like infinite scroll) 41 | 42 | Making requests with Javascript: 43 | - XMLHTTP Request 44 | - Fetch API 45 | - 3rd Party - jQuery, Axios, etc. 46 | 47 | ### XML and JSON 48 | 49 | They are data formats used in response data (mostly); API's don't respond with HTML, they respond with pure data 50 | 51 | #### XML 52 | 53 | Extended Markup Language 54 | 55 | Semantically similar to HTML, but it does not describe presentation like HTML does 56 | 57 | ```xml 58 | 59 | Some title 60 | Some author 61 | 62 | ``` 63 | 64 | #### JSON 65 | 66 | JavaScript Object Notation replaced XML (so mostly it's now AJAJ); it looks almost exactly like JS Obj 67 | 68 | ```JSON 69 | 'item': { 70 | title: 'Some title', 71 | author: 'Some author' 72 | } 73 | ``` 74 | 75 | ## Requests 76 | 77 | Workflow is usually event -> request -> data 78 | 79 | ### XMLHTTP Request (XHR) 80 | 81 | The first, original way to make requests (rarely used) 82 | 83 | ```javascript 84 | var XHR = new XMLHttpRequest(); // create new instance of request 85 | 86 | XHR.onreadystatechange = function() { 87 | // readyState can have 5 different states (from 0 to 4: unsent, opened, headers_receiver, loading, done) 88 | if (XHR.readyState == 4 && XHR.status == 200) { 89 | console.log(XHR.responseText); 90 | } else { 91 | console.log('There was a problem!'); 92 | } 93 | }; 94 | 95 | XHR.open('GET', 'https://api.github.com/zen'); // we tell what type of request we want to do, and URL 96 | XHR.send(); // what we send, we initiate request 97 | ``` 98 | 99 | #### Problems with XHR 100 | 101 | 1. Ugly, bulky syntax 102 | 2. It's 16 years old 103 | 3. No Streaming 104 | 105 | ### Fetch 106 | 107 | Is a replacement, update for XHR 108 | 109 | ```javascript 110 | fetch(url) // basically, this is a request already; it returns a promise 111 | .then(function(res) { 112 | console.log(res); // whole response object; we can use something like res.status 113 | }) 114 | .catch(function(error) { 115 | console.log(error); 116 | }); 117 | ``` 118 | 119 | Parsing JSON with Fetch: 120 | 121 | ```javascript 122 | fetch(url).then(function(res) { 123 | return res.json(); // it is promise as well (which is returned to .then after fetch(url)) 124 | // .then (from below) can be inserted here as well (not after the closing brackets of the first .then) 125 | // functionally they are the same 126 | }).then(function(data) { 127 | console.log(data); // we can work with data as an object now 128 | }).catch(function() { 129 | console.log('Problem!'); 130 | }); 131 | ``` 132 | 133 | #### Fetch Options 134 | 135 | ```javascript 136 | fetch(url, { 137 | method: 'POST', // get by default 138 | body: JSON.stringify({ 139 | name: 'blue', 140 | login: 'bluecat', 141 | }) // including object with options 142 | // we don't have to use stringify, but it makes it easier, we don't have to make manualle eash of this a string, worry about " or ' 143 | // also we can provide headers and other stuff, see more at https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch 144 | }) 145 | .then(function(response) { 146 | // do something 147 | }) 148 | .catch(function(error) { 149 | // handle error 150 | }); 151 | ``` 152 | 153 | #### Fetch Error Handling 154 | 155 | Syntax: 156 | 157 | ```javascript 158 | .fetch(url) 159 | .then(function (res) { 160 | // we put error checking in its own .then 161 | // first thing we want to do is to ckeck if everything is ok 162 | if (!res.ok) { 163 | throw Error(404); // up to us 164 | // that will trigger .catch below 165 | } 166 | return res; // if things are ok, we return response and .then is run 167 | }).then(function (response) { 168 | console.log('ok'); 169 | }).catch(function(error) { 170 | console.log(error); 171 | }); 172 | ``` 173 | 174 | Example: 175 | 176 | ```javascript 177 | var btn = document.querySelector('button'); 178 | 179 | btn.addEventListener('click', function() { 180 | var url = 'https://api.github.com/users/coltasdas'; 181 | fetch(url) 182 | .then(function() { 183 | console.log('EVERYTHING IS FINE!'); 184 | }) 185 | .catch(function() { 186 | console.log('There is a problem'); 187 | // if the user is wrong (not 'Colt'), 'Everything is fine' will be returned anyway 188 | // we will see 'There is a problem' if there is a problem with a request itself, e.g. if the internet is off, or there is a problem connection, or with credentials, but not with the actual response 189 | }); 190 | }); 191 | 192 | // we need to rewrite our code to handle different statuses 193 | 194 | btn.addEventListener('click', function() { 195 | var url = 'https://api.github.com/users/coltasdas'; 196 | fetch(url) 197 | .then(handleErrors) 198 | .then(function(request) { 199 | // to check the status we can put if request.status === 200... but we can use request.ok 200 | // request.ok is a built-in property which can be used instead of 'if status != 200' or something 201 | if (!request.ok) { 202 | // throw error 203 | console.log('Error with response status!') 204 | } 205 | // this code will still run 206 | console.log('EVERYTHING IS FINE!'); 207 | }) 208 | .catch(function() { 209 | console.log('There is a problem'); 210 | }); 211 | }); 212 | 213 | // refactor using different promises to streamline things 214 | btn.addEventListener('click', function() { 215 | var url = 'https://api.github.com/users/coltasdas'; 216 | fetch(url) 217 | .then(handleErrors) 218 | .then(function(request) { 219 | if (!request.ok) { 220 | throw Error(request.status); 221 | } 222 | return request // we need to return something if there is no error 223 | }) 224 | .then(function(request) { 225 | console.log('Everything is fine'); 226 | console.log(request); 227 | }) 228 | .catch(function(error) { 229 | console.log(error); // equals to whatever we 'throw', i.e. here response status 230 | }); 231 | }); 232 | 233 | // refactor code 234 | var btn = document.querySelector('button'); 235 | btn.addEventListener('click', function() { 236 | var url = 'https://api.github.com/users/coltasdas'; 237 | fetch(url) 238 | .then(handleErrors) 239 | .then(function(request) { 240 | console.log('EVERYTHING IS FINE!'); 241 | console.log(request); 242 | }) 243 | .catch(function(error) { 244 | console.log(error); 245 | }); 246 | }); 247 | 248 | function handleErrors (request) { 249 | if (!request.ok) { 250 | throw Error(request.status); 251 | } 252 | return request; 253 | } 254 | ``` 255 | 256 | #### Problem with Fetch 257 | 258 | The main problem is browser compatibility (IE doesn't have fetch at all) 259 | 260 | --- 261 | 262 | ## jQuery and Axios 263 | 264 | ### jQuery 265 | 266 | It can be used not only for manipulating the DOM, but for requests as well (without fetch) 267 | 268 | We need to include it first (look for jQuery CDN) 269 | 270 | #### $.ajax 271 | 272 | This is the main, 'base' method, other three are shorthand methods 273 | 274 | It just creates an XHR under the hood 275 | - https://api.jquery.com/jQuery.ajax/ (there are examples at bottom) 276 | - ``Query.ajaxSettings.xhr = function() { 277 | try { 278 | return new window.XMLHttpRequest(); 279 | } catch ( e ) {} 280 | };`` 281 | 282 | 283 | 284 | ```javascript 285 | $.ajax({ 286 | method: 'GET', 287 | url: 'some.api.com', 288 | // datatype: 'json', 289 | }) 290 | .done(function(res) { 291 | console.log(res); 292 | // data is automatically parsed (dataType parameter); we don't need to JSON.parse or data.json().then 293 | // default: intelligent guess, e.g. JSON 294 | // it's better to be explicit 295 | }) 296 | .fail(function() { 297 | // do something 298 | // fail will automatically check response code, i.e. will trigger on 404, not only problem with request itself 299 | }) 300 | ``` 301 | 302 | #### $.get 303 | 304 | Load data from the server using a HTTP GET request ($.ajax method: 'get') 305 | - https://api.jquery.com/jQuery.get/ 306 | 307 | ```javascript 308 | $("#getBtn").click(function(){ 309 | $.get('https://api.github.com/users/colt') 310 | // note that parameters are strings, so jQuery.get( url [, data ] [, success ] [, dataType ] ) 311 | .done(function(data){ 312 | console.log(data); 313 | }) 314 | .fail(function(){ 315 | console.log("ERROR!"); 316 | }) 317 | }); 318 | ``` 319 | 320 | #### $.post 321 | 322 | Load data from the server using a HTTP POST request 323 | - https://api.jquery.com/jQuery.post/ 324 | 325 | ```javascript 326 | $("#postBtn").click(function(){ 327 | var data = {name: "Charlie", city: "Florence"}; 328 | $.post("www.catsarecoolandsoaredogs.com", data) 329 | .done(function(data){ 330 | console.log("HI!"); 331 | }) 332 | .fail(function(){ 333 | console.log("ERROR!"); 334 | }) 335 | }); 336 | ``` 337 | 338 | #### $.json 339 | 340 | Load JSON-encoded data from the server using a GET HTTP request 341 | - https://api.jquery.com/jQuery.getJSON/ 342 | 343 | ```javascript 344 | $("#getJSONBtn").click(function(){ 345 | $.getJSON("https://api.github.com/users/colt") 346 | .done(function(data){ 347 | console.log(data); 348 | }) 349 | .fail(function(){ 350 | console.log("PROBLEM!"); 351 | }) 352 | }); 353 | ``` 354 | 355 | ### Axios 356 | 357 | If we don't need whole jQuery (there are many features which could be not needed), we can use some other library for making request, such as Axios 358 | 359 | Axios is a lightweight HTTP request library (creates XHR under the hood; we need to install or include it first) 360 | - Make XMLHttpRequests from the browser 361 | - Make http requests from node.js 362 | - Supports the Promise API 363 | - Intercept request and response 364 | - Transform request and response data 365 | - Cancel requests 366 | - Automatic transforms for JSON data 367 | - Client side support for protecting against XSRF 368 | - https://github.com/axios/axios 369 | 370 | ```javascript 371 | // basic example 372 | axios.get(url) 373 | .then(function(res) { 374 | console.log(res.data) 375 | }) 376 | .catch(function(e) { 377 | console.log(e); 378 | }) 379 | 380 | // usage example (get) 381 | var url = 'https://opentdb.com/api.php?amount=1'; 382 | axios.get(url) 383 | .then(function(res){ 384 | console.log(res.data.results[0].question); 385 | }) 386 | .catch(function(){ 387 | console.log("ERR"); 388 | }) 389 | ``` 390 | 391 | #### Axios Error Handling 392 | 393 | ```javascript 394 | // html: 395 | // 396 | // 397 | //
398 | 399 | var btn = document.querySelector("button"); 400 | var section = document.querySelector("#comments"); 401 | btn.addEventListener("click", sendRequest); 402 | 403 | function sendRequest(){ 404 | axios.get("https://jsonplaaskjldceholder.typicode.com/comments", { 405 | params: { 406 | postId: 1 // we can pass in an object with parameters (instead of ?postId=1 etc.) 407 | } 408 | }) 409 | .then(addComments) 410 | .catch(handleErrors) 411 | } 412 | 413 | function addComments(res) { 414 | res.data.forEach(function(comment) { 415 | appendComment(comment); 416 | }); 417 | } 418 | 419 | function appendComment(comment) { 420 | var newP = document.createElement("p"); 421 | newP.innerText = comment.email; 422 | section.appendChild(newP); 423 | } 424 | 425 | function handleErrors(err) { 426 | if (err.response) { 427 | // err.response if used for bad statuses 428 | console.log("Problem With Response ", err.response.status); 429 | } else if (err.request) { 430 | // err.request is used for bad requests 431 | console.log("Problem With Request!"); 432 | } else { 433 | console.log('Error', err.message); 434 | } 435 | } 436 | ``` -------------------------------------------------------------------------------- /advanced theory/css3.md: -------------------------------------------------------------------------------- 1 | # CSS 3 2 | 3 | #### Table of Contents 4 | 5 | - [CSS 3](#css-3) 6 | - [Table of Contents](#table-of-contents) 7 | - [CSS Animations](#css-animations) 8 | - [Pseudoclasses](#pseudoclasses) 9 | - [:hover](#hover) 10 | - [:focus](#focus) 11 | - [:active](#active) 12 | - [Transform](#transform) 13 | - [Transform: Translate](#transform-translate) 14 | - [Transform: Scale](#transform-scale) 15 | - [Transform-Origin](#transform-origin) 16 | - [Transform: Rotate](#transform-rotate) 17 | - [Browser (Vendor) Prefixes](#browser-vendor-prefixes) 18 | - [Transitions](#transitions) 19 | - [Transition Shorthands](#transition-shorthands) 20 | - [What Can Be Transitioned](#what-can-be-transitioned) 21 | - [What Should Be Transitioned](#what-should-be-transitioned) 22 | - [Keyframes](#keyframes) 23 | - [CSS Animation Properties](#css-animation-properties) 24 | - [Animation Shorthand](#animation-shorthand) 25 | - [Layout With Flexbox](#layout-with-flexbox) 26 | - [Intro to Flexbox](#intro-to-flexbox) 27 | - [Display: Flex Property](#display-flex-property) 28 | - [Flex Terminology](#flex-terminology) 29 | - [Flexbox Properties of Container](#flexbox-properties-of-container) 30 | - [Flex-direction](#flex-direction) 31 | - [Flex-wrap](#flex-wrap) 32 | - [Justify-content](#justify-content) 33 | - [Align-items](#align-items) 34 | - [Align-content](#align-content) 35 | - [Flexbox Properties of Item](#flexbox-properties-of-item) 36 | - [Align-self](#align-self) 37 | - [Order](#order) 38 | - [Flex](#flex) 39 | - [Flex-basis](#flex-basis) 40 | - [Flex-grow](#flex-grow) 41 | - [Flex-shrink](#flex-shrink) 42 | - [Holy Grail Layout](#holy-grail-layout) 43 | - [Flexbox Browser Support](#flexbox-browser-support) 44 | - [Responsiveness](#responsiveness) 45 | 46 | ## CSS Animations 47 | 48 | ### Pseudoclasses 49 | 50 | Usually animations are triggered by something, they do not happen on page load 51 | 52 | Pseudoclasses are commonly used triggers, special selectors which are added to selector and specify a special state of the selected elements (not only related to animations) 53 | - They let you apply a style to an element not only in relation to the content fo the document tree, but also in relation to external factors, e.g. 54 | - History of the navigator (:visited) 55 | - Status of the content (:checked) 56 | - Position of the mouse (:hover) 57 | 58 | Syntax: 59 | 60 | ```css 61 | selector:pseudo-class { 62 | property: value; 63 | } 64 | ``` 65 | 66 | #### :hover 67 | 68 | Trigger by a user mousing over (not necessarily activating it) 69 | 70 | ```css 71 | div:hover { 72 | background: purple; 73 | } 74 | ``` 75 | 76 | #### :focus 77 | 78 | Triggers when an element 'receives focus' (triggered when the user clicks, taps on an element or selects with 'tab') 79 | 80 | ```css 81 | input:focus { 82 | color: red; 83 | } 84 | ``` 85 | 86 | #### :active 87 | 88 | Triggers when an element is 'being activated by user' (click on an element (actual action is happening) or when it's selected by 'tab', commonly used on \ or \