diff --git a/.eslintrc.json b/.eslintrc.json index 263f18df1..1c1b99549 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,8 +1,16 @@ { - "extends": ["airbnb", "prettier"], + "extends": ["airbnb-base", "prettier"], "plugins": ["prettier"], "env": { - "browser": true + "browser": true, + "jest": true + }, + "globals": { + "page": true, + "browser": true, + "context": true, + "jestPuppeteer": true, + "axios": "readonly" }, "rules": { "prettier/prettier": ["error"], @@ -10,6 +18,7 @@ "strict": "off", "no-plusplus": "off", "linebreak-style": "off", + "no-restricted-syntax": "off", "no-param-reassign": [ "error", { diff --git a/.gitignore b/.gitignore index 6c589c2f8..171af4338 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,4 @@ typings/ .netlify dist/ +iPhoneX.png diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..469f36b11 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + "recommendations": [ + "CoenraadS.bracket-pair-colorizer", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "ritwickdey.LiveServer", + "streetsidesoftware.code-spell-checker", + "techer.open-in-browser" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index f7a55df12..183110862 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,6 +5,13 @@ "editor.detectIndentation": false, "editor.tabSize": 2, "cSpell.words": [ - "tabindex" - ] -} \ No newline at end of file + "READYSTATE", + "Traversy", + "ajaxcrash", + "networkidle", + "remarcmij", + "tabindex", + "whiteframe" + ], + "deno.enable": false +} diff --git a/README.md b/README.md index fa97dad57..55310b364 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,131 @@ -> Please help us improve and share your feedback! If you find better tutorials -or links, please share them by [opening a pull request](https://github.com/HackYourFuture/JavaScript3/pulls). +# DEPRECATED - JavaScript 3 +This module has been replace with the Using API's module, find it [here](https://github.com/HackYourFuture/UsingAPIs) -# HackYourFuture JavaScript 3 +```Welcome to JavaScript3! Congratulations on making it this far. You're well on your way to the top! -Here you can find course content and homework for the JavaScript3 modules +A big part of being a programmer means moving data from one place to another. It also means working with other people's software. In this module you'll be learning about one of the core things of what makes a web developer: working with APIs! -|Week|Topic|Read|Homework| -|----|-----|----|--------| -|1.|• Structure for a basic SPA (Single Page Application)
• [XMLHttpRequests](../../../fundamentals/blob/master/fundamentals/XMLHttpRequest.md)
• API calls|[Reading Week 1](/Week1/README.md)|[Homework Week 1](/Week1/MAKEME.md)| -|2.|• [Event Loop (order of execution)](../../../fundamentals/blob/master/fundamentals/event_loop.md)
• [Promises](../../../fundamentals/blob/master/fundamentals/promises.md)|[Reading Week 2](/Week2/README.md)|[Homework Week 2](/Week2/MAKEME.md)| -|3.|• [try...catch](../../../fundamentals/blob/master/fundamentals/try_catch.md)
• [async/await](../../../fundamentals/blob/master/fundamentals/async_await.md)
• [The `this` keyword](../../../fundamentals/blob/master/fundamentals/this.md)
• call, apply, bind
• [Object Oriented Programming and ES6 Classes](../../../fundamentals/blob/master/fundamentals/oop_classes.md)|[Reading Week 3](/Week3/README.md)|[Homework Week 3](/Week3/MAKEME.md)| +On top of that you'll also learn how to think differently about _how_ you write your programs. Like in any field, once you've mastered a particular way of doing things you start thinking about how it could be done in a smarter, different way. In programming we call these `paradigms` and in this module you'll learn one such paradigm: Object-Oriented Programming! -__Kind note:__ +## Before you start -We expect you to __always__ come prepared to the class on Sunday. +In the following weeks we will be using a "style guide" to help you write _"clean code"_. Because code is not only meant to be run by computers, but also to be read by humans (your colleagues, and the future version of you), it's best to make your code good. If your code is readable and nicely formatted, you're doing your colleages (and future you) a great service. The idea of a "style guide" comes from visual design, where companies often have a "visual style". For example, watch the following video to get an idea of this: -### Overall -A good understanding of all the above mentioned topics. Want to check your Knowledge? Go through the [JavaScript Fundamentals README](../../../fundamentals/blob/master/README.md) and research/ ask for help (Slack!) with the concepts that are not entirely clear. +### Setup Style Guide -*The HackYourFuture curriculum is subject to CC BY copyright. This means you can freely use our materials, but just make sure to give us credit for it :)* +Similar to how designers have style guides for their design work, programmers often have "programming style guides". This is set of rules to follow when writing/formatting your code. The styleguide we'll be using is the one from Airbnb: -Creative Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License. +- [Front-end Style Guides](https://fronteers.nl/congres/2015/sessions/front-end-style-guides-anna-debenham) + +The style guide we'll be using is the one from Airbnb: + +- [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript) + +While you do not need to read this guide in detail, it is recommended that you look at sections 1-8, 12-13, 15-21 and 23. + +We also have tools that can automatically check whether your code is correctly formatted according to a style guide. These tools are called "linters". We will be using the JavaScript linter called "ESLint". The following packages are already added to this repository's `package.json`: + +The required packages you need to install before you write code according to the style guide are the following: + +`json +"eslint" +"eslint-config-airbnb-base" +"eslint-config-prettier" +"eslint-plugin-import" +"eslint-plugin-prettier" +"prettier" +` + +They are already in this repository's `package.json` so all you have to do now to prepare is to execute the following command at the root of this module directory: + +`md +npm install +` + +### Forking the right repository + +Before you start with the homework, make sure you've made a fork of the right repository: [HackYourHomework/JavaScript3](https://www.github.com/hackyourhomework/javascript3)). Once you've cloned it to your computer you can proceed by making GIT branches for each week. Start at the `master` branch and execute the following (note that they're 3 different commands): + +`bash +foo@bar:~$ git branch week1-YOURNAME +foo@bar:~$ git branch week2-YOURNAME +foo@bar:~$ git branch week3-YOURNAME +` + +Then execute `git checkout week1-YOURNAME` and you can get started! + +If you have any questions or if something is not entirely clear ¯\_(ツ)\_/¯, please ask/comment on Slack! + +## Learning goals + +In order to successfully complete this module you will need to master the following: + +- Learn what an `Application Programming Interface` (API) is +- Catch up on the `history of JavaScript` +- Understand how to write more readable `asynchronous JavaScript` +- Connect with different `public APIs` +- Build a `Single Page Application` (SPA) +- Work with pre-existing code +- Learn about `Object-Oriented Programming` + +## How to use this repository + +### Repository content + +This repository consists of 3 essential parts: + +1. `README`: this document contains all the required theory you need to understand **while** working on the homework. It contains not only the right resources to learn about the concepts, but also lectures done by HackYourFuture teachers. This is the **first thing** you should start with every week +2. `MAKEME`: this document contains the instructions for each week's homework. Start with the exercises rather quickly, so that you can ground the concepts you read about earlier. +3. `LESSONPLAN`: this document is meant for teachers as a reference. However, as a student don't be shy to take a look at it as well! + +### How to study + +Let's say you are just starting out with the JavaScript3 module. This is what you do... + +1. The week always starts on **Wednesday**. First thing you'll do is open the `README.md` for that week. For the first week of `JavaScript3`, that would be [Week1 Reading](/Week1/README.md) +2. You spend **Wednesday** and **Thursday** going over the resources and try to get a basic understanding of the concepts. In the meanwhile, you'll also implement any feedback you got on last week's homework (from the JavaScript2 module) +3. On **Friday** you start with the homework, found in the `MAKEME.md`. For the first week of `JavaScript3`, that would be [Week1 Homework](/Week1/MAKEME.md) +4. You spend **Friday** and **Saturday** playing around with the exercises and write down any questions you might have +5. **DEADLINE 1**: You'll submit any questions you might have before **Saturday 23.59**, in the class channel +6. On **Sunday** you'll attend class. It'll be of the Q&A format, meaning that there will be no new material. Instead your questions shall be discussed and you can learn from others +7. You spend **Monday** and **Tuesday** finalizing your homework +8. **DEADLINE 2**: You submit your homework to the right channels (GitHub) before **Tuesday 23.59**. If you can't make it on time, please communicate it with your mentor +9. Start the new week by going back to point 1! + +In summary: + +![Weekflow](assets/weekflow.png) + +To have a more detailed overview of the guidelines, please read [this document](https://docs.google.com/document/d/1JUaEbxMQTyljAPFsWIbbLwwvvIXZ0VCHmCCN8RaeVIc/edit?usp=sharing) or ask your mentor/class on Slack! + +### Video lectures + +For each module HackYourFuture provides you with video lectures. These are made by experienced software developers who know what they're talking about. The main teacher for this module will be [Stasel Seldin](https://hackyourfuture.slack.com/team/UQJGC1MSL): senior iOS developer! + +You can find out more about him here: + +- [GitHub](https://github.com/Stasel) +- [@Stasel on Slack](https://hackyourfuture.slack.com/team/UQJGC1MSL) + +Learn from Stasel in the following playlist of videos he has made for you! (Click on the image to open the link) + +HYF Video + +## Planning + +| Week | Topic | Reading Materials | Homework | Lesson Plan | +| ---- | ------------------------------------------------------------------------------------------- | ------------------------------ | ------------------------------- | -------------------------------------- | +| 1. | Application Programming Interface (API), AJAX, Modules & Libraries | [Reading W1](/Week1/README.md) | [Homework W1](/Week1/MAKEME.md) | [Lesson Plan W1](/Week1/LESSONPLAN.md) | +| 2. | Promises, Fetch API, JavaScript Versions, 'this' keyword, Arrow functions | [Reading W2](/Week2/README.md) | [Homework W2](/Week2/MAKEME.md) | [Lesson Plan W1](/Week2/LESSONPLAN.md) | +| 3. | Object-Oriented Programming (OOP), ES6 Classes, Async/await, Thinking like a programmer III | [Reading W3](/Week3/README.md) | [Homework W3](/Week3/MAKEME.md) | [Lesson Plan W1](/Week3/LESSONPLAN.md) | +| 4. | Final JavaScript Test | [Details](test.md) | - | - | + +## Finished? + +Did you finish the module? High five! + +If you feel ready for the next challenge, click [here](https://www.github.com/HackYourFuture/Node.js) to go to Node.js! + +_The HackYourFuture curriculum is subject to CC BY copyright. This means you can freely use our materials, but just make sure to give us credit for it :)_ + +Creative Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License.``` diff --git a/Week1/LESSONPLAN.md b/Week1/LESSONPLAN.md new file mode 100644 index 000000000..a0d1c8f0e --- /dev/null +++ b/Week1/LESSONPLAN.md @@ -0,0 +1,141 @@ +# Lesson Plan JavaScript3 Week 1 + +## Agenda + +The purpose of this class is to introduce to the student: + +- What are `APIs` and how to interact with them +- What is `AJAX` and how to apply it (`XMLHttpRequest`) +- How to use libraries (`axios`) + +## Core concepts + +FIRST HALF (12.00 - 13.30) + +## 1. What are APIs and how to interact with them + +### Explanation +- APIs are created by providers and used by consumers (BE provider, FE consumer) +- Part of an application that can be communicated with from an outside source +- Connect to it using "endpoints" +- Software well-known APIs (Fb APIs, Twitter APIs, Maps APIs, weather APIs); +- API doesn't care which language or technology is used in the consumer or the provider + +#### Types of APIs: +- Private: for employees only under a company network for internal use. +- Semi-private: for clients who paid for the API. +- Public: for everyone on the web. + +#### Architecture styles of API: +- Single purpose: API that gives a direct and specific service. +- Aggregated API: one API as a wrapper for multiple APIs. +- Web services API: punch of APIs working together to forma whole app. + +#### Basic structure of REST API + +- Endpoint: https://api.example.com +- Endpoint with version: https://api.example.com/v1 +- Resources: +* https://api.example.com/v1/users +* https://api.example.com/v1/users/create +* https://api.example.com/v1/users/1 +* https://api.example.com/v1/users/1/edit +- Query params: +* https://api.example.com/v1/users?limit=10 +### Example +- Give real life example like (Devices like TV, any machine + electricity power socket interface which provides power to any external device) + +### Excercise + +### Essence +- Mostly used to request data from some service +- Communication between software and user needs UI interface but software and software needs API as an interface. + +## 2. What is `AJAX` and how to apply it (`XMLHttpRequest`) + +### Explanation +- Before AJAX all page reload for all requests, via refreshing the url in the address bar with the new resource. +- It's a technique, not a technology +- `AJAX` stands for Asynchronous JavaScript and XML +- Nowadays we use `JSON` instead of `XML` +- Fetch data without reloading the page +- The XMLHttpRequest API is defined in the browser (window.XMLHttpRequest) +### Example +Example using the XMLHttpRequest + +```javascript +const oReq = new XMLHttpRequest(); +oReq.open('GET', `https://api.openweathermap.org/data/2.5/weather?q=${cityName}`); +oReq.send(); +oReq.addEventListener('load', function (event) { + const data = JSON.parse(this.response); + if (data.cod >= 400) { + // error + console.log(data.message); + } else { + //success + console.log(data.coord.lat); + } +}); + +// or another way of getting data +oReq.load = function (event) { + // use oReq.response or this.response + const data = JSON.parse(this.response); + if (data.cod >= 400) { + // error + console.log(data.message); + } else { + //success + console.log(data.coord.lat); + } +}; + +``` + +### Excercise + +Steps of doing the following example:- +** Install the live server plugin in VS (go to plugins -> live server -> install) +1. Create self-invoked function to wrap your code +2. Create an object instance of `XMLHttpRequest` +3. Call the `open` function to fill it with the Request URL and the request Method +4. Call the `send` function to make the request +5. Add event listener with a callback for the sucess event `load` + +### Essence + +SECOND HALF (14.00 - 16.00) + +## 3. How to use libraries (`axios`) + +### Explanation +- A library is a code solution a developer (or a team) has written to a common problem +- Usually open-source +- Helps to solve a problem within an application +- Read the documentation on how to use it +### Example +Same example but using axios +```javascript +axios + .get(`https://api.openweathermap.org/data/2.5/weather?q=${cityName}`) + .then(function (response) { + // handle success + console.log(response.data); + }).catch(function (error) { + // handle error + console.log(error); + }).finally(function () { + // always be executed + console.log('I am always here') + }); +``` + +> Note: Give example at the end with binding/showing these data in a DOM element like a
or a list instead of only showing them on the console using console.log. + +### Excercise +### Essence + + + + diff --git a/Week1/MAKEME.md b/Week1/MAKEME.md index eed3987c8..6f040f6bc 100644 --- a/Week1/MAKEME.md +++ b/Week1/MAKEME.md @@ -1,251 +1,134 @@ -# Homework Week 1 +# Homework JavaScript3 Week 1 -``` -Topics discussed this week: -• Structure for a basic SPA -• XMLHttpRequests -• API calls -``` - -## Step 1: Single Page Application :sweat_drops: - -**_Deadline Thursday_** - -_This homework is more extensive and challenging than previous homework! Please read the instructions below carefully and follow them with great attention to detail. Start this homework as soon as you can and allow time for discussion and questions (slack!)._ - -### 1.1 Introduction - -> In this assignment you will built upon some existing code that is already pre-written by your teachers. Your homework consist of writing the code to make the application work as requested per week. - -You are going to write a _Single Page Application_ (SPA) that uses the [GitHub API](https://developer.github.com/guides/getting-started/). - -This application should display information about the available [HYF GitHub repositories](https://github.com/hackyourfuture). The functionalities we would like to see in your application are as follows: - -- The user should be able to select a repository from a list of available repositories. -- The application should display high-level information about the selected repository and show a list of its contributors. -- When clicking on the name of the selected repository the GitHub page for the corresponding repository should be opened in a new browser tab. -- When clicking on a contributor, the GitHub page for the contributor should be opened in a new browser tab. - -Figure 1 below shows an example of what your application could look like. Note that this is just an example. If you find it boring or unimaginative, please improve on it! On the other hand, a simpler version is OK too, so long as you implement the expected functionality. - -![UI Example](./assets/hyf-github.png) - -Figure 1. Example User Interface using [Material Design](https://material.io/guidelines/) principles. - -A live version of this application can be found here: http://hyf-github.netlify.com/ - -### 1.2 The GitHub API - -#### 1.2.1 Get a list of HYF repositories - -You can fetch a list of HYF repositories through this API endpoint ([What is an API Endpoint?](https://teamtreehouse.com/community/what-is-an-api-endpoint)): - -``` -https://api.github.com/orgs/HackYourFuture/repos?per_page=100 -``` - -If you open this URL in the browser (_try it!_) you will receive JSON data about the available HYF repositories. This is the data that you will need to work with in this assignment. - -Note the query string `?per_page=100` in the above URL. If you don't specify this query string you will only get the first 30 repositories (the default `per_page` is 30). HackYourFuture has more than 30 repositories but less than 100. - -The returned JSON data contains some basic information about each repository, such as `name`, `full_name`, `description` etc. There are also many properties that contain URLs that can be used to obtain detail information about certain aspects of the repository. - -#### 1.2.2 Get contributor information for a repository - -The JSON data that is returned from the initial request to get repository information includes a property named `contributors_url`. Use the value of this property to fetch a list of contributors. - -#### 1.2.3 GitHub API documentation - -You can find detailed information about the GitHub API by means of the link listed below. However, the documentation is very extensive and not easy to digest. For this homework it is not necessary to study the GitHub API documentation. We provide the link here for completeness. +## **Todo list** -> GitHub API documentation: https://developer.github.com/v3/ +1. Practice the concepts +2. JavaScript exercises +3. Code along +4. PROJECT: Hack Your Repo I -### 1.3 Coding Style +## **1. Practice the concepts** -In this homework we will be introducing a preferred coding style and supporting tools to help you write _"clean code"_. A number of popular [_JavaScript Style Guides_](https://codeburst.io/5-javascript-style-guides-including-airbnb-github-google-88cbc6b2b7aa) have recently emerged of which the one developed by [Airbnb](https://github.com/airbnb/javascript) has been chosen for this homework and is recommended for subsequent use during the HYF curriculum. It is documented here: +This week's concepts can be challenging, therefore let's get an easy introduction using some interactive exercises! Check the following resources out and start practicing: -- [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript) +- [Learn JavaScript: Requests](https://www.codecademy.com/learn/introduction-to-javascript/modules/intermediate-javascript-requests) -While you do not need to read this guide in detail, it is recommended that you review sections 1-8, 12-13, 15-21 and 23. The tools installed during the project preparation step below will help you to implement these guidelines in your code. You will see error and warning messages in the VSCode editor when your code deviates from the recommended style. An additional check will be done when you submit your homework as a pull request on GitHub. +## **2. JavaScript exercises** -### 1.5 Preparation +> Inside of your `JavaScript3` fork and inside of the `Week1` folder, create a folder called `homework`. Inside of that folder, create a folder called `js-exercises`. For all the following exercises create a new `.js` file in that folder (3 files in total). Make sure the name of each file reflects its content: for example, the filename for exercise one could be `getRandomUser.js`. -You will be working on the same application during the next three weeks. For each week you will need to create a new Git branch, as listed in the Table 1 below. +**Exercise 1: Who do we have here?** -| Week | Branch | Assignment | -| :--: | ------- | -------------------------------------------------------------------------------------------------------------------------------- | -| 1 | `week1` | - Create a basic application using callbacks to handle network requests. | -| 2 | `week2` | Based on the `week1` branch:
- Refactor the callbacks to promises.
- Make the UI responsive. | -| 3 | `week3` | Based on the `week2` branch:
- Refactor the application to use ES6 Classes and async/await.
- Make the app ARIA-compliant. | +Wouldn't it cool to make a new friend with just the click of a button? -Table 1. Homework schedule +Write a function that makes a HTTP Request to `https://www.randomuser.me/api` -**Instructions** +- Inside the JavaScript file write two functions: one with `XMLHttpRequest`, and the other with `axios` +- Each function should make a HTTP Request to the given endpoint: `https://www.randomuser.me/api` +- Log the received data to the console +- Incorporate error handling: log to the console the error message -1. Fork the JavaScript3 repository (_this repository_) to your own GitHub account. -2. Clone the fork to your laptop. -3. Open the newly created `JavaScript3` folder from the cloned repository in VSCode. -4. Install the following extension in VSCode: +**Exercise 2: Programmer humor** - **Prettier - Code formatter**. +Who knew programmers could be funny? -5. Open a Terminal window in VSCode and type the following command to install Prettier and ESLint tools as required for the homework: +Write a function that makes a HTTP Request to `https://xkcd.now.sh/?comic=latest` - ``` - npm install - ``` +- Inside the same file write two programs: one with `XMLHttpRequest`, and the other with `axios` +- Each function should make a HTTP Request to the given endpoint: `https://xkcd.now.sh/?comic=latest` +- Log the received data to the console +- Render the `img` property into an `` tag in the DOM +- Incorporate error handling: log to the console the error message -6. Create a new branch for the week 1 homework with the following command: +**Exercise 3: Dog photo gallery** - ``` - git checkout -b week1 - ``` +Let's make a randomized dog photo gallery! -### 1.5 Code Overview +Write a function that makes a HTTP Request to `https://dog.ceo/api/breeds/image/random`. It should trigger after clicking a button in your webpage. Every time the button is clicked it should append a new dog image to the DOM. -The files that make up the application are located in the `homework` folder. It contains the following files: +- Create an `index.html` file that will display your random image +- Add 2 ` + +

+

User

+
+

Users

+
+ + + + diff --git a/Week1/traversy_ajax_crash/ajax2.js b/Week1/traversy_ajax_crash/ajax2.js new file mode 100644 index 000000000..58225f09c --- /dev/null +++ b/Week1/traversy_ajax_crash/ajax2.js @@ -0,0 +1,56 @@ +'use strict'; + +{ + function loadUser() { + const xhr = new XMLHttpRequest(); + xhr.open('GET', 'user.json', true); + + xhr.onload = () => { + if (xhr.status === 200) { + const user = JSON.parse(xhr.responseText); + + let output = ''; + + output += + ``; + + document.getElementById('user').innerHTML = output; + } + }; + + xhr.send(); + } + + function loadUsers() { + const xhr = new XMLHttpRequest(); + xhr.open('GET', 'users.json', true); + + xhr.onload = () => { + if (xhr.status === 200) { + const users = JSON.parse(xhr.responseText); + + let output = ''; + + for (const user of users) { + output += + ``; + } + + document.getElementById('users').innerHTML = output; + } + }; + + xhr.send(); + } + + document.getElementById('button1').addEventListener('click', loadUser); + document.getElementById('button2').addEventListener('click', loadUsers); +} diff --git a/Week1/traversy_ajax_crash/ajax3.html b/Week1/traversy_ajax_crash/ajax3.html new file mode 100644 index 000000000..8ccbdbbaa --- /dev/null +++ b/Week1/traversy_ajax_crash/ajax3.html @@ -0,0 +1,29 @@ + + + + + + + Codestin Search App + + + + +

+

Github Users

+
+ + + + diff --git a/Week1/traversy_ajax_crash/ajax3.js b/Week1/traversy_ajax_crash/ajax3.js new file mode 100644 index 000000000..3cbe12dbf --- /dev/null +++ b/Week1/traversy_ajax_crash/ajax3.js @@ -0,0 +1,32 @@ +'use strict'; + +{ + // Load Github Users + function loadUsers() { + const xhr = new XMLHttpRequest(); + xhr.open('GET', 'https://api.github.com/users', true); + + xhr.onload = () => { + if (xhr.status === 200) { + const users = JSON.parse(xhr.responseText); + + let output = ''; + for (const user of users) { + output += + `
` + + `` + + `
`; + } + + document.getElementById('users').innerHTML = output; + } + }; + + xhr.send(); + } + + document.getElementById('button').addEventListener('click', loadUsers); +} diff --git a/Week1/traversy_ajax_crash/sample.txt b/Week1/traversy_ajax_crash/sample.txt new file mode 100644 index 000000000..9e1cc3268 --- /dev/null +++ b/Week1/traversy_ajax_crash/sample.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore beatae vitae nulla itaque, assumenda optio libero maxime perferendis fugit, vel et ad tenetur fuga temporibus. Adipisci laboriosam veritatis eaque atque reiciendis. Modi expedita neque libero fugit adipisci molestiae? Porro harum consequuntur excepturi minima corporis culpa quisquam non at quia quaerat? \ No newline at end of file diff --git a/Week1/traversy_ajax_crash/user.json b/Week1/traversy_ajax_crash/user.json new file mode 100644 index 000000000..539f902a2 --- /dev/null +++ b/Week1/traversy_ajax_crash/user.json @@ -0,0 +1,5 @@ +{ + "id":1, + "name":"Rick", + "email":"rick@gmail.com" +} \ No newline at end of file diff --git a/Week1/traversy_ajax_crash/users.json b/Week1/traversy_ajax_crash/users.json new file mode 100644 index 000000000..857664f2d --- /dev/null +++ b/Week1/traversy_ajax_crash/users.json @@ -0,0 +1,17 @@ +[ + { + "id":1, + "name":"Rick", + "email":"rick@gmail.com" + }, + { + "id":2, + "name":"Glenn", + "email":"glenn@gmail.com" + }, + { + "id":3, + "name":"Negan", + "email":"negan@gmail.com" + } +] diff --git a/Week2/LESSONPLAN.md b/Week2/LESSONPLAN.md new file mode 100644 index 000000000..59587c5f4 --- /dev/null +++ b/Week2/LESSONPLAN.md @@ -0,0 +1,462 @@ +# Lesson Plan JavaScript3 Week 2 + +## Agenda + +The purpose of this class is to introduce to the student: + +- How to use the `fetch` API to do AJAX calls +- The structure and use of `Promises` +- The `this` keyword and its relationship with `scope` + +## Core concepts + +FIRST HALF (12.00 - 13.30) + +## 1. Promises + +### Explanation +- JS versions https://www.w3schools.com/js/js_versions.asp + - the javascript language evolves, new things are added and some thing become obsolete +- It's a way to introduce asynchronicity to your application +- Makes asynchronous code read like it's synchronous + + +In the examples `setTimeout` is used to illustrate asynchronous code. In the real world there will be some code doing useful work here, for example `fetch`. + +**Callback** +```javascript +let didFinishHomework = true; +let doHomeWork = function (cb) { + setTimeout(function () { + if ( didFinishHomework ) + cb(null); // call callback function with NO error and no data + else + cb(new Error('homework not done, too lazy')); // call callback function with error + }, 1000); +} + + +doHomeWork(function (err) { + if ( err ) + console.warn(err.message); + else + console.log('home work is done now'); +}) +``` + +**Promise** +```javascript +let didFinishHomework = true; +let promiseToDoHomeWork = new Promise(function (resolve, reject) { + setTimeout(function () { + if ( didFinishHomework ) + resolve(); // goto then + else + reject(new Error('homework not done, too lazy')); // goto catch and pass the error + }, 1000); +}); + +promiseToDoHomeWork + .then(function () { console.log('home work is done now'); }) + .catch(function (err) { console.warn(err); }) + +``` + +**!!! Students should watch this video !!!** +- https://youtu.be/RvYYCGs45L4 + + +### Example + +#### Nested callback/promises example + +```javascript +let attendClass = function (cb) { + setTimeout(function () { + if ( true ) + cb(null, 'I attend the class'); // call the callback function with no Error and some data + else + cb(new Error('class not attended, stayed home')); // call the callback function with an Error + }, 1000); +} + +let didFinishHomework = true; +let doTheHomeWork = function (message, cb) { + setTimeout(function () { + if ( didFinishHomework ) + cb(null, message + ' then I did the homework'); // call the callback function with no Error and some data + else + cb(new Error('homework not done, was lazy')); // call the callback function with an Error + }, 1000); +} + +let submitHomeWork = function (message, cb) { + setTimeout(function () { + if ( true ) + cb(null, message + ' so I submit my homework'); // call the callback function with no Error and some data + else + cb(new Error('homework not submited, github is down')); // call the callback function with an Error + }, 1000); +} + +// call attendClass, after it is finished call doTheHomeWork then submitHomeWork. In each step pass the output of the previous step. In case of an error show it in the console + +attendClass(function (err, data) { + if ( err ) + console.warn(err.message); + else + doTheHomeWork(data, function (err1, data1) { + if ( err1 ) + console.warn(err1.message); + else + submitHomeWork(data1, function (err2, data2) { + if ( err2 ) + console.warn(err2.message); + else + console.log(data2) + }); + }) +}) +``` +Mention how this nested structure is hard to understand and read. Multiple variables with similar names and error handling is all over the place. +Simulate an error in doTheHomeWork by setting `didFinishHomework = false` and run the example again + +```javascript + +let attendClass = function () { + return new Promise(function (resolve, reject) { + setTimeout(function () { + if ( true ) + resolve('I attend the class'); // goto then and pass the data + else + reject(new Error('class not attended, stayed home')); // goto catch and pass the error + }, 1000); + }); +} + +let didFinishHomework = true; +let doTheHomeWork = function (message) { + return new Promise(function (resolve, reject) { + setTimeout(function () { + if ( true ) + resolve(message + ' then I did the homework'); // goto then and pass the data + else + reject(new Error('homework not done, was lazy')); // goto catch and pass the error + }, 1000); + }); +} + +let submitHomeWork = function (message) { + return new Promise(function (resolve, reject) { + setTimeout(function () { + if ( true ) + resolve(message + ' so I submit my homework'); // goto then and pass the data + else + reject(new Error('homework not submited, github is down')); // goto catch and pass the error + }, 1000);; + }); +} + +attendClass() + .then(function (result) { + return doTheHomeWork(result); + }) + .then(function (result) { + return submitHomeWork(result); + }) + .then(function (result) { + console.log(result); + }) + .catch(function (error) { // catches all errors + console.warn(error.message); + }); + + +``` +Simulate an error in doTheHomeWork by setting `didFinishHomework = false` and run the example again. + +- Promise.all + +Imagine that you are cleaning your house. If you are going to to it alone then it will take you the whole day. However if you ask your friend to help then you can be done in half the time. + +```javascript +Promise.all([cleanKitchen("Me"), cleanBathroom("friend")]).then(function ([res1, res2]) { console.log('all finished') }); +``` + +- Promise.race + +Sometimes I get really hungry. Then I want to eat as soon as possible. So I order a pizza. But I never know how long it will take for the pizza to arrive. And I am really hungry. So I start frying some potatotes. When at one of them is ready either the pizza has arrived or the frites are done then I will eat and I do not have to wait for the other one. + +```javascript +Promise.race([fryPotatoes(), orderPizza()]).then(function (food) { console.log('I am eating: '+food) }); +``` + +### Exercise + +#### Easy exercise (see difficult exercise alternative below) + +**Part 1** +Rewrite the following code to use promise instead of callbacks. *As preparation for `fetch`* + +```javascript +{ +const WEATHER_URL = `https://api.openweathermap.org/data/2.5/weather?q=amsterdam&appid=316f8218c0899311cc029a305f39575e`; + +function fetchResourceAsCallback(url, cb) { + const oReq = new XMLHttpRequest(); + oReq.open('GET', url); + oReq.send(); + oReq.addEventListener('load', function (event) { + const response = JSON.parse(this.response); + if (response.code >= 400) { + // error + cb(new Error("Failed to get because:"+response));/´// call callback function with an error + } else { + //success + cb(null, response); // call callback function with NO error and pass the response + } + }); +} + +fetchResourceAsCallback(WEATHER_URL, + function (err, data) { + if ( err ) + console.warn(err.message); + else + console.log(data); + } +); + +function fetchResourceAsPromise(url) { + // your code goes in here +} + +fetchResourceAsPromise(WEATHER_URL) +.then(function (result) { + console.log(result); +}) +.catch(function (err) { + console.warn(err.message); +}); +} + +``` + +**Part 2** + +Use `Promise.all` to load data for multiple cities in parallel. Ask students to discuss in which scenarios it would be better to load data in parallel. In what scenarios is loading data in parallel not better. + +```javascript + +const URLS_TO_LOAD = [ 'https://samples.openweathermap.org/data/2.5/weather?q=London&appid=316f8218c0899311cc029a305f39575e', 'https://api.openweathermap.org/data/2.5/weather?q=amsterdam&appid=316f8218c0899311cc029a305f39575e']; +``` + +* Hint: use `map` to convert from an array of URLs to an array of promises. + +**Alternative exercise - Cooking pasta** + +**❗❗❗ Difficult exercise ❗❗❗** + +> Async can be hard to understand without real live example. Cooking is a great example of mixed synchronous and asynchronous tasks. In this assignment we'll cook pasta with promises 💍 + + +Let's say we want a program to cook some pasta. Some of the steps involved in cooking pasta are: + +1. Gathering the ingredients (pasta, garlic, tomatoes, sage, butter) +2. Cutting the garlic +3. Cutting the tomatoes +4. Cooking the water +5. Cooking the pasta +6. Baking the garlic +7. Baking the tomatoes + X. Mixing the pasta with sauce + +If we do this synchronously there is no chance of it becoming a good meal because the pasta would be cold by the time the vegetables are ready. It would also take way too long this way. So let's fix that! + +1. Think about how to do this asynchronously; which tasks could be run at the same time? What steps should wait for what other steps? Try to write down a basic recipe (don't write any code yet!) +2. Now convert your recipe to pseudocode (in markdown). The point is to name functions and show which functions call which other functions. The logic should be there but we'll write the code in the next step. +3. Write the actual code using promises. Add timeouts to each task (estimate how many minutes a task would take and then set the timeout to that many seconds so 8 minutes for cooking pasta would be 8 seconds in your programme) +4. Can you get the code to work like you would cook pasta in the kitchen? Try using Promise.all if you want to wait for several tasks to finish. + + + +> Async await really helps simplify asynchronous (promisified) code. The previous example can be improved by applying it. + +5. Try rewriting your previous attempt using Async/Await. ⏰🍝⏰ + + + +### Essence + +- It's the accepted solution to [callback hell](http://callbackhell.com/) +- in terms of features it does not offer something new, everything one can do with promises could also be done with callbacks but it is easier to write and read the code when promises are used + +## 2. How to use the `fetch` API to do AJAX calls + +### Explanation +- Modern replacement of XMLHttpRequest +- Uses Promise structure +- The Fetch API is defined in the browser (window.fetch) +- Only modern browsers support it (show [caniuse.com](https://caniuse.com/#feat=fetch)) +- Fetch API documentations by mozilla [link](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) +### Example + +### Excercise +``` +fetch('https://seriousnews.com/api/headlines') + .then(function (response) { + response.json(); + }).then(headlines => { + console.log(headlines) + }).catch(error => console.log(error)); +``` +### Essence + +SECOND HALF (14.00 - 16.00) + +## 3. The `this` keyword and its relationship with `scope` + +### Explanation +- The environment(or scope) in which the line is being executed is know as “Execution Context” +- The object that `this` refers to, changes every time execution context is changed. +- Whatever is calling the function passes the `this` value to it by default. +- We can pass specific `this` by `.bind`, `.call` or `.apply` +- By default, “this” refers to global object which is `global` in case of NodeJS and `window` object in case of browser + +### Example + +#### this refers to new instance (constructors) + +```javascript +function logColor() { + // this inside the function refers to the calling javascript object + console.log('This refers to: ',this); + console.log('Color of this is: '+this.color); +} +let dog = { age: 5, color: 'brown', logColor: logColor}; +let car = { model: 'bmw', color: 'orange', logColor: logColor }; + +console.log('log color called with dog') +dog.logColor(); +console.log('log color called with car') +car.logColor(); +``` + +- In Javascript, property of an object can be a method or a simple value. +- When an Object’s method is invoked then “this” refers to the object which contains the method being invoked. + + +#### “this” refers to global object +```javascript +function logColor() { + // this inside the function refers to the calling javascript object + console.log('This refers to: ',this); + console.log('Color of this is: '+this.color); +} + +console.log('log color called with no object') +logColor(); // no calling object so "this" refers to window by default +``` +> Note: the value of “this” depends on how a method is being invoked as well. + +#### “this” with call, apply methods +- These methods can be used to set custom value of `this` to the execution context of function, also they can pass arguments/parameters to the function + +```javascript +function logColor() { + // this inside the function refers to the calling javascript object + console.log('This refers to: ',this); + console.log('Color of this is: '+this.color); +} +let cat = { likes: 'milk', color: 'white'}; +logColor.call(cat); // calls the logColor function with cat as "this" +``` + +#### “this” with bind method +`bind` only create a copy of the function with the binded `this` inside without calling the function. +``` +function callAfterOneSecond(cb) { + setTimeout(function () { + cb(); + }, 1000); +} +function logColor() { + // this inside the function refers to the calling javascript object + console.log('This refers to: ',this); + console.log('Color of this is: '+this.color); +} +let cat = { likes: 'milk', color: 'white'}; +let boundLogColor = logColor.bind(cat); // returns a function that can be executed later +console.log(boundLogColor); +// a few lines later +boundLogColor(); // executes logColor with cat as "this" + +// callAfterOneSecond(boundLogColor); +``` + + +> Note: If `strict mode` is enabled for any function then the value of “this” will be “undefined” as in strict mode, global object refers to undefined in place of windows object. + +``` +function foo() { + 'use strict'; + console.log("Simple function call") + console.log(this === window); +} + +foo(); //prints false on console as in “strict mode” value of “this” in global execution context is undefined. +``` + +#### “this” in arrow functions +- The `this` value inside the arrow function gets binded and calculated and assigned based on its wrapper/container/parent `this` value. +- The methods call(), apply(), and bind() will not change the value of this in arrow functions + +Students will learn mroe about this when learning about classes in javascript. + + +### Excercise +In this excercise, let the students guess the result and then go line by line as if you were an interpreter and execute the code. Or use the debugger tools on devtools to execute line by line. + + +```javascript +let user = { + a: 2, + b: 3, + print: function () { + console.log(multiply(this.a, this.b)); + } +} +user.a = 5; +user.print(); +user.b = 10; +function multiply(p, q) { + return p * q; +} +``` + +Variant two (if students find variant one too easy) + +```javascript +let user = { + a: 2, + b: 3, + print: function () { + multiply(this.a, this.b, function (total) { + console.log(total); + console.log(this.a * this.b); + }) + } +} +user.a = 5; +user.print() +user.b = 10; +function multiply(p, q, callback) { + callback(p * q); +} +``` + +### Essence +this is special keyword in javascript. this refers to different things depending on how a function is called. + + + diff --git a/Week2/MAKEME.md b/Week2/MAKEME.md index e35660898..d4f082dee 100644 --- a/Week2/MAKEME.md +++ b/Week2/MAKEME.md @@ -1,85 +1,130 @@ -# Homework Week 2 +# Homework JavaScript3 Week 2 -``` -Topics discussed this week: -• Async vs Sync -• Event Loop (order of execution) -• Promises +## **Todo list** + +1. Practice the concepts +2. JavaScript exercises +3. Code along +4. PROJECT: Hack Your Repo II + +## **1. Practice the concepts** + +Let's start this week off with some interactive exercises! Visit the following link to get started: + +- [Learn JavaScript: Promises](https://www.codecademy.com/learn/introduction-to-javascript/modules/javascript-promises) + +## **2. JavaScript exercises** + +> Inside of your `JavaScript3` fork and inside of the `Week2` folder, create a folder called `homework`. Inside of that folder, create a folder called `js-exercises`. For all the following exercises create a new `.js` file in that folder (3 files in total). Make sure the name of each file reflects its content: for example, the filename for exercise one could be `getName.js`. + +**Exercise 1: John who?** + +Take a look at the following function (and try it out in your console): + +```js +const getAnonName = (firstName, callback) => { + setTimeout(() => { + if (!firstName) + return callback(new Error("You didn't pass in a first name!")); + + const fullName = `${firstName} Doe`; + + return callback(fullName); + }, 2000); +}; + +getAnonName('John', console.log); ``` -## Step 1: Read +Rewrite this function, but replace the callback syntax with the Promise syntax: -- Read this article on scopes & closures: [explaining-javascript-scope-and-closures](https://robertnyman.com/2008/10/09/explaining-javascript-scope-and-closures/) +- Have the `getAnonName` function return a `new Promise` that uses the `firstName` parameter +- If the Promise `resolves`, pass the full name as an argument to resolve with +- If the Promise `rejects`, pass an error as the argument to reject with: "You didn't pass in a first name!" -- If you are still not completely clear on promises, here are some additional resources :ring: +**Exercise 2: Is it bigger than 10?** - - [Google's post about Promises](https://developers.google.com/web/fundamentals/getting-started/primers/promises) - - [A nice article from David Walsh](https://davidwalsh.name/promises) - - [A real life example](https://github.com/mdn/js-examples/blob/master/promises-test/index.html) - - [stackoverflow](http://stackoverflow.com/questions/13343340/calling-an-asynchronous-function-within-a-for-loop-in-javascript) - - YouTube: [promises](https://www.youtube.com/watch?v=WBupia9oidU) +Write a function called `checkDoubleDigits` that: -## Step 2: Implement requested PR changes +- Takes 1 argument: a number +- Returns a `new Promise` +- If the number is bigger than 10, resolve with the string: "The number is bigger than 10!" +- If the number is smaller than 10, reject with the error: "Error! The number is smaller than 10..." -- Fix Requested Changes (if any) on the Pull Request. +**Exercise 3: Gotta catch 'em all** -## Step 3: Convert callbacks to promises +> Inside of your `homework` folder, create another folder called `pokemon-app`. There, create an `index.html` and `script.js` file -**_Deadline Thursday_** +Let's catch all original 151 Pokemon in our own little web application! Here's an example of what you'll be building for this exercise: -### 3.1 Preparation +![Pokemon App](./../assets/pokemon-app.gif) -The homework for week 2 will build on the work you did in week 1. You will create a new branch based on the `week1` branch. +In this exercise you're going to do several things: -1. Make sure that you committed all changes in the week 1 version of your homework. -2. Create a new `week2` branch: +1. Create and append DOM elements using JavaScript only +2. Fetch data twice from a public API [PokeAPI](https://pokeapi.co/) +3. Display the results in the DOM. - ``` - git checkout -b week2 - ``` +Here are the requirements: -### 3.2 Assignment +- Create 3 functions: `fetchData`, `addPokemonToDOM` and `main` +- The `main` function executes the other functions and contains all the variables +- In the `fetchData` function, make use of `fetch` and its Promise syntax in order to get the data from the public API +- Execute the `main` function when the window has finished loading -You will continue to work on the files `index.js` and (possibly) `style.css`. +## **3. Code along** -- Complete your GitHub app code from the previous week, if needed, to meet the requirements from that week's assignment. -- Replace all asynchronous callbacks (e.g. as used with XMLHttpRequest) by ES6 promises. -- Beautify your app's styling. -- If not yet completed in week 1, make your app responsive (use CSS media queries and [Flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/)). +In the following "code along" you'll be building a complete Weather App that makes use of the [Darksky API](https://darksky.net). -### 3.3 Handing in your homework +Enjoy! -If necessary, review the instructions how to [Hand in homework](https://github.com/HackYourFuture/fundamentals/blob/master/fundamentals/homework_pr.md) using GitHub pull request. +- [Build a Weather App with Vanilla JavaScript Tutorial](https://www.youtube.com/watch?v=wPElVpR1rwA) -To test whether your code will be accepted when you submit your homework as a pull request you need to ensure that it does not contain ESLinr errors. Open a terminal window in VSCode and type the following command: +## **4. PROJECT: Hack Your Repo II** +> This week we'll continue building on our work from last week. Make sure to navigate to the `hackyourrepo-app` folder and start based on the code you wrote! + +This week we'll do a couple of things: + +1. We'll remove our HTML elements and remake them using JavaScript only! +2. We'll replace our placeholder data with real data from the GitHub API +3. We'll display this data in a separate column of the user interface + +On the surface, it'll look exactly the same. But functionally, it'll based around JavaScript only! + +Here are the requirements: + +- Remove the HTML elements you created last week, and only keep the ` + + diff --git a/Week2/traversy_async_crash/promises.js b/Week2/traversy_async_crash/promises.js new file mode 100644 index 000000000..97a1428b4 --- /dev/null +++ b/Week2/traversy_async_crash/promises.js @@ -0,0 +1,68 @@ +const posts = [ + { title: 'Post One', body: 'This is post one' }, + { title: 'Post Two', body: 'This is post two' }, +]; + +function getPosts() { + setTimeout(() => { + let output = ''; + posts.forEach(post => { + output += `
  • ${post.title}
  • `; + }); + document.body.innerHTML = output; + }, 1000); +} + +function createPost(post) { + return new Promise((resolve, reject) => { + setTimeout(() => { + posts.push(post); + + const error = false; + + if (!error) { + resolve(); + } else { + reject(new Error('Something went wrong')); + } + }, 2000); + }); +} + +// createPost({ title: 'Post Three', body: 'This is post three' }) +// .then(getPosts) +// .catch(err => console.log(err)); + +// Async / Await +// async function init() { +// await createPost({ title: 'Post Three', body: 'This is post three' }); + +// getPosts(); +// } + +// init(); + +// Async / Await / Fetch +async function fetchUsers() { + const res = await fetch('https://jsonplaceholder.typicode.com/users'); + + const data = await res.json(); + + console.log(data); +} + +fetchUsers(); + +// Promise.all +// const promise1 = Promise.resolve('Hello World'); +// const promise2 = 10; +// const promise3 = new Promise((resolve, reject) => +// setTimeout(resolve, 2000, 'Goodbye') +// ); +// const promise4 = fetch('https://jsonplaceholder.typicode.com/users').then(res => +// res.json() +// ); + +// Promise.all([promise1, promise2, promise3, promise4]).then(values => +// console.log(values) +// ); diff --git a/Week3/LESSONPLAN.md b/Week3/LESSONPLAN.md new file mode 100644 index 000000000..356427f3b --- /dev/null +++ b/Week3/LESSONPLAN.md @@ -0,0 +1,48 @@ +# Lesson Plan JavaScript3 Week 3 + +## Agenda + +The purpose of this class is to introduce to the student: + +- The purpose and use of `async/await` +- What is `Object-Oriented Programming` (OOP) is and how it's applied to JavaScript +- How to use ES6 `classes` + +## Core concepts +FIRST HALF (12.00 - 13.30) +## 1. async/await + +### Explanation +- It's an upgrade to `Promises` +- Makes writing an asynchronous function more readable +### Example +### Excercise +### Essence + + +## 2.Object-Oriented Programming (OOP) + +### Explanation +- It's a programming style; it defines how to organise your application +- In OOP each program would be split up into self-contained objects, that then communicate with each other +- Each object represents a part of the application: it contains its own data and logic +- OOP is meant to make thinking about your applications easier, by having each object represent a real-life entity (i.e. Users, Profiles, Products) +### Example +### Excercise +### Essence + + +SECOND HALF (14.00 - 16.00) + +## 3.ES6 classes + +### Explanation +- `classes` are a modern way of creating objects in JavaScript +- It's `syntactical sugar` for object constructors +- A `class` is a blueprint of an object, that can be instantiated +### Example +### Excercise +### Essence + + + diff --git a/Week3/MAKEME.md b/Week3/MAKEME.md index ab57382f2..7e1046f70 100644 --- a/Week3/MAKEME.md +++ b/Week3/MAKEME.md @@ -1,135 +1,163 @@ -# Homework Week 3 +# Homework JavaScript3 Week 3 -``` -Topics discussed this week: -• Object Oriented Programming and ES6 Classes -• The this keyword -• call, apply, bind -``` +## **Todo list** -## Step 1: Fix requested changes +1. Practice the concepts +2. JavaScript exercises +3. Code along +4. PROJECT: Hack Your Repo III -_Deadline Monday_ +## **1. Practice the concepts** -- Fix Requested Changes (if any) on the Pull Request. +Let's continue exercising those programming muscles! Go through the following exercises: -## Step 2 +- [Learn JavaScript: Objects](https://www.codecademy.com/learn/introduction-to-javascript/modules/learn-javascript-objects) +- [Learn JavaScript: Classes](https://www.codecademy.com/learn/introduction-to-javascript/modules/learn-javascript-classes) +- [Learn JavaScript: Async/Await](https://www.codecademy.com/learn/introduction-to-javascript/modules/asynch-js) -**_Deadline Thursday_** +## **2. JavaScript exercises** -### 2.1 Preparation +> Inside of your `JavaScript3` fork and inside of the `Week3` folder, create a folder called `homework`. Inside of that folder, create a folder called `js-exercises`. For all the following exercises create a new `.js` file in that folder (3 files in total). Make sure the name of each file reflects its content: for example, the filename for exercise one could be `getName.js`. -**Read the fundamental pages on:** +**Exercise 1: Promise me to wait** -- [try...catch](../../../../fundamentals/blob/master/fundamentals/try_catch.md) -- [async/await](../../../../fundamentals/blob/master/fundamentals/async_await.md) +In this exercise you'll practice refactoring `Promise` syntax into `async/await` + `try/catch` syntax. Rewrite exercise A & B using `async/await` + `try/catch` syntax. -The homework for week 3 will build on the work you did in week 2. You will create a new branch based on the `week2` branch. +```js +// Exercise A +function getData(url) { + fetch(url) + .then(response => response.json) + .then(json => console.log(json)) + .catch(error => console.log(error)); +} -1. Make sure that you committed all changes in the week 2 version of your homework. -2. Create a new `week3` branch: +getData('https://randomfox.ca/floof/'); - ``` - git checkout -b week3 - ``` +// Exercise B +const arrayOfWords = ['cucumber', 'tomatos', 'avocado']; -### 2.2 Assignment +const makeAllCaps = array => { + return new Promise((resolve, reject) => { + let capsArray = array.map(word => { + if (typeof word === 'string') { + return word.toUpperCase(); + } else { + reject('Error: Not all items in the array are strings!'); + } + }); + resolve(capsArray); + }); +}; -This week you will work with all JavaScript files in the `src` folder. The assignment consists of two parts: +makeAllCaps(arrayOfWords) + .then(result => console.log(result)) + .catch(error => console.log(error)); +``` -1. Refactor all `.then()` and `.catch()` methods with `async`/`await` and `try...catch`. -2. Make your app ARIA-compliant (see below). -3. Refactor your application to use ES6 classes. +**Exercise 2: Classify** -#### 2.2.1 async/await +In this exercise you'll read a little story. It's your job to turn the characters in it into classes and instantiate the class into the characters you read about! -**Instructions:** +```md +# STORY -1. Refactor all `.then()` and `.catch()` methods with `async`/`await` and `try...catch`. +Abdulkareem is a 35 year old man, that lives in Riyadh. He has a wife and 3 children. As a day job he's a construction worker, that makes houses. He likes to eat dates and smoke water pipe. -2. Make sure that your error handling code still works. See the week2 MAKEME on how to force an error response from GitHub. +Abdulkareem has a horse, named Adel. The horse is 15 years old and has the color brown. Usually the horse eats grass or helps transport materials for Abdulkareem. -#### 2.2.2 ES6 Classes +And they lived happily ever after! +``` -**_Deadline Saturday_** +After reading this story, you have to: -This final assignment requires you to go the extra mile and master Object Oriented Programming and ES6 classes. +- Create a class for Adbulkareem and Adel +- Instantiate those classes to create an Abdulkareem object and Adel object -In this assignment you need to redistribute and adapt the code from `index.js` to the files `App.js`, `Repository.js` and `Contributor.js`. You do not need to modify `Util.js`. +**Exercise 3: Trivia time!** -| File | Description | -| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `index2.html` | You should load this HTML file in your browser instead of `index.html` to work with the classes version of your homework. It loads the following JavaScript files through ` + + diff --git a/Week3/traversy_fetch_api/sample.txt b/Week3/traversy_fetch_api/sample.txt new file mode 100644 index 000000000..03ffbce09 --- /dev/null +++ b/Week3/traversy_fetch_api/sample.txt @@ -0,0 +1 @@ +I am a sample text file \ No newline at end of file diff --git a/Week3/traversy_fetch_api/users.json b/Week3/traversy_fetch_api/users.json new file mode 100644 index 000000000..857664f2d --- /dev/null +++ b/Week3/traversy_fetch_api/users.json @@ -0,0 +1,17 @@ +[ + { + "id":1, + "name":"Rick", + "email":"rick@gmail.com" + }, + { + "id":2, + "name":"Glenn", + "email":"glenn@gmail.com" + }, + { + "id":3, + "name":"Negan", + "email":"negan@gmail.com" + } +] diff --git a/Week3/traversy_oop_crash/1_basics_literals.js b/Week3/traversy_oop_crash/1_basics_literals.js new file mode 100644 index 000000000..be9f63cca --- /dev/null +++ b/Week3/traversy_oop_crash/1_basics_literals.js @@ -0,0 +1,21 @@ +// Object Literal +const book1 = { + title: 'Book One', + author: 'John Doe', + year: 2013, + getSummary: function() { + return `${this.title} was written by ${this.author} in ${this.year}.`; + }, +}; + +const book2 = { + title: 'Book Two', + author: 'Jane Doe', + year: 2016, + getSummary: function() { + return `${this.title} was written by ${this.author} in ${this.year}.`; + }, +}; + +console.log(book1.getSummary()); +console.log(book2.getSummary()); diff --git a/Week3/traversy_oop_crash/2_constructor.js b/Week3/traversy_oop_crash/2_constructor.js new file mode 100644 index 000000000..311ca291d --- /dev/null +++ b/Week3/traversy_oop_crash/2_constructor.js @@ -0,0 +1,20 @@ +// Constructor +function Book(title, author, year) { + this.title = title; + this.author = author; + this.year = year; + this.getSummary = function() { + return `${this.title} was written by ${this.author} in ${this.year}.`; + }; +} + +// Instantiate an Object +const book1 = new Book('Book One', 'John Doe', 2013); +const book2 = new Book('Book Two', 'Jane Doe', 2016); + +console.log(book1.getSummary()); +console.log(book2.getSummary()); + +console.log(book1); + +book1.turnPage(); diff --git a/Week3/traversy_oop_crash/3_prototypes.js b/Week3/traversy_oop_crash/3_prototypes.js new file mode 100644 index 000000000..abaf231fd --- /dev/null +++ b/Week3/traversy_oop_crash/3_prototypes.js @@ -0,0 +1,34 @@ +// Constructor +function Book(title, author, year) { + this.title = title; + this.author = author; + this.year = year; +} + +Book.prototype.getSummary = function() { + return `${this.title} was written by ${this.author} in ${this.year}.`; +}; + +Book.prototype.getAge = function() { + const years = new Date().getFullYear() - this.year; + return `${this.title} is ${years} years old.`; +}; + +// Revise / Change Year +Book.prototype.revise = function(newYear) { + this.year = newYear; + this.revised = true; +}; + +// Instantiate an Object +const book1 = new Book('Book One', 'John Doe', 2013); +const book2 = new Book('Book Two', 'Jane Doe', 2016); + +console.log(book1.getSummary()); +console.log(book2.getSummary()); + +console.log(book2); +book2.revise(2018); +console.log(book2); + +console.log(book2.getAge()); diff --git a/Week3/traversy_oop_crash/4_inheritance.js b/Week3/traversy_oop_crash/4_inheritance.js new file mode 100644 index 000000000..91c7b7fa1 --- /dev/null +++ b/Week3/traversy_oop_crash/4_inheritance.js @@ -0,0 +1,37 @@ +// Book Constructor +function Book(title, author, year) { + this.title = title; + this.author = author; + this.year = year; +} + +Book.prototype.getSummary = function() { + return `${this.title} was written by ${this.author} in ${this.year}.`; +}; + +Book.prototype.getAge = function() { + const years = new Date().getFullYear() - this.year; + return `${this.title} is ${years} years old.`; +}; + +// Magazine Constructor +function Magazine(title, author, year, month) { + Book.call(this, title, author, year); + this.month = month; +} + +// Inherit Prototype +Magazine.prototype = Object.create(Book.prototype); + +// Use Magazine Constructor +Magazine.prototype.constructor = Magazine; + +Magazine.prototype.updateMonth = function(month) { + this.month = month; +}; + +// Instantiate Magazine Object +const mag1 = new Magazine('Mag One', 'John Doe', 2018, 'Jan'); + +console.log(mag1); +console.log(mag1.getSummary()); diff --git a/Week3/traversy_oop_crash/5_object_create.js b/Week3/traversy_oop_crash/5_object_create.js new file mode 100644 index 000000000..90a73204b --- /dev/null +++ b/Week3/traversy_oop_crash/5_object_create.js @@ -0,0 +1,25 @@ +// Object of Protos +const bookProtos = { + getSummary: function() { + return `${this.title} was written by ${this.author} in ${this.year}.`; + }, + getAge: function() { + const years = new Date().getFullYear() - this.year; + return `${this.title} is ${years} years old.`; + }, +}; + +// Create Object +const book1 = Object.create(bookProtos); +book1.title = 'Book One'; +book1.author = 'John Doe'; +book1.year = 2013; + +const book2 = Object.create(bookProtos, { + title: { value: 'Book Two' }, + author: { value: 'Jane Doe' }, + year: { value: 2016 }, +}); + +console.log(book1); +console.log(book2); diff --git a/Week3/traversy_oop_crash/6_classes.js b/Week3/traversy_oop_crash/6_classes.js new file mode 100644 index 000000000..5349c0008 --- /dev/null +++ b/Week3/traversy_oop_crash/6_classes.js @@ -0,0 +1,42 @@ +class Book { + constructor(title, author, year) { + this.title = title; + this.author = author; + this.year = year; + } + + getSummary() { + return `${this.title} was written by ${this.author} in ${this.year}.`; + } + + getAge() { + const years = new Date().getFullYear() - this.year; + return `${this.title} is ${years} years old.`; + } + + revise(newYear) { + this.year = newYear; + this.revised = true; + } + + static topBookStore() { + return 'Barnes & Noble'; + } +} + +// Instantiate an Object +const book1 = new Book('Book One', 'John Doe', 2013); +const book2 = new Book('Book Two', 'Jane Doe', 2016); + +console.log(book1); + +console.log(book1.getSummary()); +console.log(book2.getSummary()); + +console.log(book2); +book2.revise(2018); +console.log(book2); + +console.log(book2.getAge()); + +console.log(Book.topBookStore()); diff --git a/Week3/traversy_oop_crash/7_subclasses.js b/Week3/traversy_oop_crash/7_subclasses.js new file mode 100644 index 000000000..d69a1db7a --- /dev/null +++ b/Week3/traversy_oop_crash/7_subclasses.js @@ -0,0 +1,28 @@ +class Book { + constructor(title, author, year) { + this.title = title; + this.author = author; + this.year = year; + } + + getSummary() { + return `${this.title} was written by ${this.author} in ${this.year}.`; + } +} + +class Magazine extends Book { + constructor(title, author, year, month) { + super(title, author, year); + this.month = month; + } + + updateMonth(month) { + this.month = month; + } +} + +// Instantiate Magazine Object +const mag1 = new Magazine('Mag One', 'John Doe', 2018, 'Jan'); + +console.log(mag1); +console.log(mag1.getSummary()); diff --git a/Week3/traversy_oop_crash/README.md b/Week3/traversy_oop_crash/README.md new file mode 100644 index 000000000..25bfed3a4 --- /dev/null +++ b/Week3/traversy_oop_crash/README.md @@ -0,0 +1,362 @@ +# OOP Crash Course + +This README is a companion to Brad Traversy's YouTube [JavaScript OOP Crash Course (ES5 & ES6)](https://www.youtube.com/watch?v=vDJpGenyHaA&t=1055s). It describes how one of the key concepts of Object Oriented Programming, **inheritance**, is implemented in JavaScript. Both explicit (pre-ES6) **prototype-based inheritance** as well as ES6 **classes-based inheritance** is covered. However, the principles of OOP itself are not discussed in this document. + +Note that it is not necessary in your daily programming to have full knowledge of all the finer details of prototypal inheritance. As can be seen in this document those details can quickly become rather complex. An overall awareness of the concept of a **prototype** chain as the underlying infrastructure for supporting inheritance will suffice. + +What _is_ important is that you understand the **ES6 class syntax** and how to implement a **class inheritance** with the **extends** keyword (see **6_classes** and **7_subclasses** below). + +>Note: The names of the sections below correspond to the equally named JavaScript example files. + +To run the code: + +1. Open **index-all.html** by right-clicking the file in the VSCode Explorer and select **Open with Live Server**. +2. Open the Chrome Developer Tools console. +3. Select the file to run from the select box. + +To examine a particular example in the Chrome Developer Tools, modify **index.html** to load the desired JavaScript file and open **index.html** in the browser. + +## 1_basics_literals + +This is the most direct way of 'manually' creating objects and does not introduce any new concepts. + +## 2_constructors + +Prior to ES6, prototypal inheritance required the use of **constructor** functions. These are regular JavaScript functions that are intended to be used in combination with the `new` keyword. By convention, constructor function names start with an upper case letter (CamelCase). + +When a function is called with `new`, its `this` value will be set to an empty object. By default, this empty object is linked through its **prototype chain** to [`Object.prototype`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#Object_instances_and_Object_prototype_object) (which in itself is an object). That is why methods such as `.hasOwnProperty()` and `.toString()` can be called on _any_ object: they are defined on `Object.prototype`. This is illustrated in Figure 1 below which corresponds to the following code snippet: + +```js +function Book(title, author, year) { + this.title = title; + this.author = author; + this.year = year; + this.getSummary = function() { + //... + }; +} + +const book1 = new Book('Book One', 'John Doe', 2013); +const book2 = new Book('Book Two', 'Jane Doe', 2016); +``` + +In this example, each **Book** object gets, in addition to its data properties, its own copy of the `.getSummary()` method. This is wasteful in both memory space and execution time. Instead, shared functions should be assigned to the prototype of the constructor function, as will be shown in the next section. + + +![2_constructor](./assets/2_constructor.png) +Figure 1. Prototypal linkage and the prototype chain. + +Note that all object instances created with the same constructor function share a single copy of the function's prototype object: + +```js +book1.__proto__ === Book.prototype // true +book2.__proto__ === Book.prototype // true +``` + +Output from `console.log(book1)`: + +``` +Book {title: "Book One", author: "John Doe", year: 2013, getSummary: ƒ} + author: "John Doe" + getSummary: ƒ () + title: "Book One" + year: 2013 + __proto__: + constructor: ƒ Book(title, author, year) + __proto__: + constructor: ƒ Object() + hasOwnProperty: ƒ hasOwnProperty() + isPrototypeOf: ƒ isPrototypeOf() + ... +``` + +## 3_prototypes + +Functions assigned to the prototype of the constructor function are shared across all object instances created with that same constructor function, as shown in Figure 2. + +```js +function Book(title, author, year) { + this.author = author; + this.title = title; + this.year = year; +} + +Book.prototype.getSummary = function() { + //... +}; + +Book.prototype.getAge = function() { + //... +}; + +Book.prototype.revise = function(newYear) { + //... +}; + +const book1 = new Book('Book One', 'John Doe', 2013); +const book2 = new Book('Book Two', 'Jane Doe', 2016); +``` + +![3_prototypes](./assets/3_prototypes.png) +Figure 2. Methods defined in the prototype of the constructor function are shared by all object instances. + +When calling a method (using dot notation) on an object, JavaScript will first look on the object itself for the method. If not found, it will inspect the **prototype** of the object (using its `__proto__` property). If still not found it will go to the next prototype in the chain, and so on, ultimately arriving at `Object.prototype` for a final inspection. + +For instance, the method `.getSummary()` is not found on the `book1` object. Following the prototype chain, JavaScript finds it on `Book.prototype`. In another example, `.toString()` is not found on the `book1` object, nor on its `Book.prototype`. It _is_ however found on `Object.prototype`. + +But if we attempt to call a `.turnPage()` method on `book1` JavaScript will not find it on the object itself, nor anywhere on its prototype chain. Consequently, JavaScript will throw a run time error: + +```js +book1.turnPage(); // Uncaught TypeError: book1.turnPage is not a function +``` + +Output from `console.log(book1)`: + +``` +Book {title: "Book One", author: "John Doe", year: 2013} + author: "John Doe" + title: "Book One" + year: 2013 + __proto__: + getAge: ƒ () + getSummary: ƒ () + revise: ƒ (newYear) + constructor: ƒ Book(title, author, year) + __proto__: + constructor: ƒ Object() + hasOwnProperty: ƒ hasOwnProperty() + isPrototypeOf: ƒ isPrototypeOf() + ... +``` + +## 4_inheritance + +An object can inherit behaviour from another object through prototypal linkage. In this example, a **Magazine** object becomes an extended version of a **Book** object. All methods from the base object are also accessible from the inheriting object and both object use a shared **this** value. + +```js +function Book(title, author, year) { + this.title = title; + this.author = author; + this.year = year; +} + +Book.prototype.getSummary = function() { + //... +}; + +Book.prototype.getAge = function() { + //... +}; + +function Magazine(title, author, year, month) { + Book.call(this, title, author, year); + this.month = month; +} + +Magazine.prototype = Object.create(Book.prototype); +Magazine.prototype.constructor = Magazine; + +Magazine.prototype.updateMonth = function(month) { + //... +}; + +const mag1 = new Magazine('Mag One', 'John Doe', 2018, 'Jan'); +``` + + +Firstly, remember that when a function is called with `new`, its `this` value is initialized with an empty object (prototype linked to `Object.prototype`). + +In order to initialize the base object (in this example **Book**), its constructor function must be called, with the `this` value set to that of the calling constructor (here, **Magazine**). + +This is done with the [Function.prototype.call()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call) method (see Figure 4 below), passing the `this` value of the calling constructor as its first argument. If the called constructor expects arguments they are passed as additional arguments following the `this` value. In this example, the called constructor for **Book** expects the arguments `title`, `author` and `year`. + +```js +function Magazine(title, author, year, month) { + Book.call(this, title, author, year); + //... +} +``` + +Next, the prototype of the calling constructor must be linked to the called constructor. This is done with the help of [Object.create()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create). + +```js +Magazine.prototype = Object.create(Book.prototype); +``` + +Finally, we must update the `.constructor` property of the prototype to point to the correct constructor function. + +```js +Magazine.prototype.constructor = Magazine; +``` + +With all this, the prototypal linkage is complete, as shown in Figure 3 below. + +![4_inheritance](./assets/4_inheritance.png) +Figure 3. Prototype chain from explicit prototypal inheritance. + +From [MDN instanceof](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof): _The **instanceof operator** tests whether the prototype property of a constructor appears anywhere in the prototype chain of an object._ + +```js +console.log(mag1 instanceof Magazine); // true +console.log(mag1 instanceof Book); // true +console.log(mag1 instanceof Object); // true +``` + +Output from `console.log(mag1)`: + +``` +Magazine {title: "Mag One", author: "Jon Doe", year: 2018, month: "Jan"} + author: "John Doe" + month: "Jan" + title: "Mag One" + year: 2018 + __proto__: Book + constructor: ƒ Magazine(title, author, year, month) + updateMonth: ƒ (month) + __proto__: + getAge: ƒ () + getSummary: ƒ () + constructor: ƒ Book(title, author, year) + __proto__: + constructor: ƒ Object() + hasOwnProperty: ƒ hasOwnProperty() + isPrototypeOf: ƒ isPrototypeOf() + ... +``` + +![function_proto](./assets/function_proto.png) +Figure 4. Every JavaScript function is prototype-linked to `Function.prototype`, which in its turn if is linked to `Object.prototype`. A function can have properties and methods, just like any object. + +```js +console.log(typeof Book === 'function'); // true +console.log(Book instanceof Function); // true +console.log(Book instanceof Object); // true +console.log(Book.__proto__ === Function.prototype); // true +console.log(typeof Function === 'function'); // true +``` + +## 5_object_create + +The method of implementing prototypal inheritance demonstrated in this example is uncommon in practice and will not be further discussed here. + +## 6_classes.js + +The pre-ES6 method of implementing explicit prototypal linkage is rather cumbersome as you may have concluded already. Fortunately, ES6 classes make implementing inheritance far simpler as shown in the code snippets below. They still use prototypal linkage behind the scenes, but using a more elegant syntax, familiar from other object-oriented languages such as Java, C++ and C#. This more palatable class syntax in ES6 JavaScript is sometimes referred to as _syntactic sugar_. + +```js +class Book { + constructor(title, author, year) { + this.title = title; + this.author = author; + this.year = year; + } + + getSummary() { + //... + } + + getAge() { + //... + } + + revise(newYear) { + //... + } +} + +const book1 = new Book('Book One', 'John Doe', 2013); +const book2 = new Book('Book Two', 'Jane Doe', 2016); +``` + +Similar to the non-ES6 case, all object instances created from the same class share a single copy of its underlying prototype object: + +```js +book1.__proto__ === Book.prototype // true +book2.__proto__ === Book.prototype // true +``` + +![6_classes](./assets/6_classes.png) +Figure 5. ES6 classes: identical to Figure 1, except that the Book constructor is now a `class`. + +Output from `console.log(book1)`: + +``` +Book {title: "Book One", author: "John Doe", year: 2013} + author: "John Doe" + title: "Book One" + year: 2013 + __proto__: + constructor: class Book + getAge: ƒ getAge() + getSummary: ƒ getSummary() + revise: ƒ revise(newYear) + __proto__: + constructor: ƒ Object() + hasOwnProperty: ƒ hasOwnProperty() + isPrototypeOf: ƒ isPrototypeOf() + ... +``` + + +## 7_subclasses + +Inheriting from a base class is easy using ES6 class syntax. A class can inherit from another class by means of the `extends` keyword. This automatically sets up the required prototypal linkage, as shown in Figure 6 below. + +```js +class Book { + constructor(title, author, year) { + this.title = title; + this.author = author; + this.year = year; + } + + getSummary() { + //... + } +} + +class Magazine extends Book { + constructor(title, author, year, month) { + super(title, author, year); + this.month = month; + } + + updateMonth(month) { + //... + } +} + +const mag1 = new Magazine('Mag One', 'John Doe', 2018, 'Jan'); +``` + +In OOP parlance, the class that inherits from the base class (in this example, **Magazine**) is called a **subclass** of the class it extends. The base class itself (here, **Book**) is called the **superclass**. + +![7_subclasses](./assets/7_subclasses.png) +Figure 6. ES6 class-based inheritance: `extends`. + +```js +console.log(mag1 instanceof Magazine); // true +console.log(mag1 instanceof Book); // true +console.log(mag1 instanceof Object); // true +``` + +Output from `console.log(mag1)`: + +``` +Magazine {title: "Mag One", author: "Jon Doe", year: 2018, month: "Jan"} + author: "Jon Doe" + month: "Jan" + title: "Mag One" + year: 2018 + __proto__: Book + constructor: class Magazine + updateMonth: ƒ updateMonth(month) + __proto__: + constructor: class Book + getSummary: ƒ getSummary() + __proto__: + constructor: ƒ Object() + hasOwnProperty: ƒ hasOwnProperty() + isPrototypeOf: ƒ isPrototypeOf() + ... +``` diff --git a/Week3/traversy_oop_crash/assets/2_constructor.png b/Week3/traversy_oop_crash/assets/2_constructor.png new file mode 100644 index 000000000..3273ed14b Binary files /dev/null and b/Week3/traversy_oop_crash/assets/2_constructor.png differ diff --git a/Week3/traversy_oop_crash/assets/3_prototypes.png b/Week3/traversy_oop_crash/assets/3_prototypes.png new file mode 100644 index 000000000..c6adfe891 Binary files /dev/null and b/Week3/traversy_oop_crash/assets/3_prototypes.png differ diff --git a/Week3/traversy_oop_crash/assets/4_inheritance.png b/Week3/traversy_oop_crash/assets/4_inheritance.png new file mode 100644 index 000000000..20b015418 Binary files /dev/null and b/Week3/traversy_oop_crash/assets/4_inheritance.png differ diff --git a/Week3/traversy_oop_crash/assets/6_classes.png b/Week3/traversy_oop_crash/assets/6_classes.png new file mode 100644 index 000000000..a682e3c1e Binary files /dev/null and b/Week3/traversy_oop_crash/assets/6_classes.png differ diff --git a/Week3/traversy_oop_crash/assets/7_subclasses.png b/Week3/traversy_oop_crash/assets/7_subclasses.png new file mode 100644 index 000000000..bee3ede9a Binary files /dev/null and b/Week3/traversy_oop_crash/assets/7_subclasses.png differ diff --git a/Week3/traversy_oop_crash/assets/function_proto.png b/Week3/traversy_oop_crash/assets/function_proto.png new file mode 100644 index 000000000..b873bf80a Binary files /dev/null and b/Week3/traversy_oop_crash/assets/function_proto.png differ diff --git a/Week3/traversy_oop_crash/index-all.html b/Week3/traversy_oop_crash/index-all.html new file mode 100644 index 000000000..2c521f00f --- /dev/null +++ b/Week3/traversy_oop_crash/index-all.html @@ -0,0 +1,23 @@ + + + + + + + Codestin Search App + + +

    Brad Traversy's OOP Crash Course

    + + + + diff --git a/Week3/traversy_oop_crash/index-all.js b/Week3/traversy_oop_crash/index-all.js new file mode 100644 index 000000000..c55ea7e5c --- /dev/null +++ b/Week3/traversy_oop_crash/index-all.js @@ -0,0 +1,13 @@ +'use strict'; + +{ + const select = document.getElementById('select'); + select.addEventListener('change', async () => { + console.clear(); + console.log(select.value); + const response = await fetch(select.value); + const code = await response.text(); + // eslint-disable-next-line no-eval + eval(code); + }); +} diff --git a/Week3/traversy_oop_crash/index.html b/Week3/traversy_oop_crash/index.html new file mode 100644 index 000000000..847313fc3 --- /dev/null +++ b/Week3/traversy_oop_crash/index.html @@ -0,0 +1,12 @@ + + + + + + + Codestin Search App + + + + + diff --git a/apps/hackyourinfo/index.js b/apps/hackyourinfo/index.js old mode 100644 new mode 100755 diff --git a/apps/hackyourinfo/package.json b/apps/hackyourinfo/package.json old mode 100644 new mode 100755 diff --git a/apps/hackyourinfo/yarn.lock b/apps/hackyourinfo/yarn.lock old mode 100644 new mode 100755 diff --git a/assets/API.png b/assets/API.png new file mode 100644 index 000000000..374cedca9 Binary files /dev/null and b/assets/API.png differ diff --git a/assets/OOP.png b/assets/OOP.png new file mode 100644 index 000000000..12adc9c5c Binary files /dev/null and b/assets/OOP.png differ diff --git a/assets/homework-submission.png b/assets/homework-submission.png new file mode 100644 index 000000000..d5962dee2 Binary files /dev/null and b/assets/homework-submission.png differ diff --git a/assets/javascript3.png b/assets/javascript3.png new file mode 100644 index 000000000..fe3fc019a Binary files /dev/null and b/assets/javascript3.png differ diff --git a/assets/pokemon-app.gif b/assets/pokemon-app.gif new file mode 100644 index 000000000..0eae9ca6a Binary files /dev/null and b/assets/pokemon-app.gif differ diff --git a/assets/stasel.png b/assets/stasel.png new file mode 100644 index 000000000..0ea55707c Binary files /dev/null and b/assets/stasel.png differ diff --git a/assets/submit-homework.png b/assets/submit-homework.png new file mode 100644 index 000000000..9d577a58e Binary files /dev/null and b/assets/submit-homework.png differ diff --git a/assets/trivia-app.gif b/assets/trivia-app.gif new file mode 100644 index 000000000..27be8dd2d Binary files /dev/null and b/assets/trivia-app.gif differ diff --git a/assets/weekflow.png b/assets/weekflow.png new file mode 100644 index 000000000..9da097126 Binary files /dev/null and b/assets/weekflow.png differ diff --git a/hackyourrepo-app/hyf.png b/hackyourrepo-app/hyf.png new file mode 100755 index 000000000..76bc5a13b Binary files /dev/null and b/hackyourrepo-app/hyf.png differ diff --git a/homework/index2.html b/hackyourrepo-app/index.html old mode 100644 new mode 100755 similarity index 67% rename from homework/index2.html rename to hackyourrepo-app/index.html index 2d1fc8fa7..2b202e708 --- a/homework/index2.html +++ b/hackyourrepo-app/index.html @@ -12,16 +12,14 @@ - Codestin Search App - + Codestin Search App + - -
    - - - - + diff --git a/hackyourrepo-app/script.js b/hackyourrepo-app/script.js new file mode 100755 index 000000000..a2206d1ed --- /dev/null +++ b/hackyourrepo-app/script.js @@ -0,0 +1,5 @@ +"use strict"; + +/* + Write here your JavaScript for HackYourRepo! +*/ diff --git a/hackyourrepo-app/style.css b/hackyourrepo-app/style.css new file mode 100755 index 000000000..5b3acae8a --- /dev/null +++ b/hackyourrepo-app/style.css @@ -0,0 +1,3 @@ +/* + Write here your CSS rules for HackYourRepo! +*/ diff --git a/hand-in-homework-guide.md b/hand-in-homework-guide.md new file mode 100644 index 000000000..710ff3cf3 --- /dev/null +++ b/hand-in-homework-guide.md @@ -0,0 +1,37 @@ +# How to hand in homework + +In this module you'll submit your homework only using GIT and GitHub. + +1. [GitHub](https://www.github.com/HackYourFuture/JavaScript3) + +## 1. GitHub homework guide + +HYF Video + +Watch the video (by clicking the image) or go through the following walk-through to learn how to submit your homework: + +ONE TIME ONLY (START OF EVERY MODULE) + +1. Create a [fork](https://help.github.com/en/articles/fork-a-repo) of the following repository: [HackYourHomework/JavaScript3](https://www.github.com/hackyourhomework/javascript3). You do this by using the `fork` option on the top right +2. Navigate to the URL of the forked repository (it should be in your personal GitHub account, under "repositories", under the name `/JavaScript3`) +3. Clone the repository, using SSH, to your local machine. You can do this by typing in `git clone ` in the command line +4. On your local machine, navigate to the folder using the command line +5. Make sure you've cloned it correctly by running `git status` and `git remote -v` from the command line + +EVERY WEEK + +1. Create a new branch for each week you have homework. For example, for the week 1 homework for JavaScript3 create a branch called `week-1-homework-YOUR_NAME` +2. Inside the week folder, create another folder called `homework`. Create your homework files in there, while on the correct branch +3. Once you're finished, `add` and `commit` everything. Make the commit message meaningful, for example `finished project for homework week1` +4. Push the branch to your forked repository (`/JavaScript3`) +5. On the GitHub page of this repository, click on the `create pull request` button. Make sure the `base repository` is `HackYourHomework/JavaScript3`, on branch master +6. Give the pull request a title in the following format: + +```markdown +Homework week 1 +``` + +7. Submit the pull request from your forked repository branch into the `master` branch of the original repository (`HackYourHomework/JavaScript3`) +8. Do a little victory dance because you did it! Good job! + +If you have any questions or if something is not entirely clear ¯\\\_(ツ)\_/¯, please ask/comment on Slack! diff --git a/homework/App.js b/homework/App.js deleted file mode 100644 index 32b71e34b..000000000 --- a/homework/App.js +++ /dev/null @@ -1,81 +0,0 @@ -'use strict'; - -/* global Util, Repository, Contributor */ - -class App { - constructor(url) { - this.initialize(url); - } - - /** - * Initialization - * @param {string} url The GitHub URL for obtaining the organization's repositories. - */ - async initialize(url) { - // Add code here to initialize your app - // 1. Create the fixed HTML elements of your page - // 2. Make an initial XMLHttpRequest using Util.fetchJSON() to populate your element with sorted