25 |
26 |
27 |
28 |
29 |
30 | ```
31 |
32 | Make a new file called `doggos.js` and put the following:
33 |
34 | ```js
35 | const BREEDS_URL = "https://dog.ceo/api/breeds/image/random";
36 |
37 | const promise = fetch(DOG_URL);
38 |
39 | promise
40 | .then(function(response) {
41 | const processingPromise = response.json();
42 | return processingPromise;
43 | })
44 | .then(function(processedResponse) {
45 | console.log(breeds);
46 | });
47 |
48 | console.log("this will log first");
49 | ```
50 |
51 | We're using a browser function here called `fetch`. `fetch` is the new way of doing AJAX and it is so much easier than the old one. Never use the old one. What `fetch` returns is called a **promise** and it's similar to a callback that we used before. A promise, like callbacks, allows you to deal with things that don't happen immediately, things that are asynchronous. In this case, we're waiting for the API to respond with the information we asked for. It takes to request more information over the Internet and we don't want to hold up the rest of our code.
52 |
53 | With a promise, it's an object that represents the future answer to whatever you asked. That's sort of weird, but it ends up being convenient. So, we have this promise, and with it we call the `then` method on it and give it a function to run once that asynchronous action (the API request) finishes.
54 |
55 | The response will look something like:
56 |
57 | ```json
58 | {
59 | "status": "success",
60 | "message": "https://images.dog.ceo/breeds/affenpinscher/n02110627_11783.jpg"
61 | }
62 | ```
63 |
64 | If that looks like JavaScript it's because it's technically valid JavaScript! It makes it really easy to use with JavaScript. Once it finishes, it gives you back an unuseful blob of stuff though. We know this blob is actually given to us in a special format called **JSON** (lol more acronyms.) JSON stands for JavaScript Object Notation, and it's a very common way to exchange data over the Internet because it's machine readable but also pretty readable to humans. Because we know this response will be in JSON (we know that because the [documentation][docs] say so) we can say process this blob into a JavaScript object we can use.
65 |
66 | However processing this into JSON is not always trivial. If you have a lot stuff to process, it can take a lot of time and computer processing to do so. As such, this made asynchronous as well and it returns a promise. That's why we do the `return processingPromise;` line. This is called **promise chaining**. The next `then` will be called once this processing is finished.
67 |
68 | Once finished, it's a normal JavaScript we can access normally. So try (inside of the function with `processedResponse`): `console.log(processedResponse.status)`. It should log out `"success"`. Cool, right?
69 |
70 | So now what I want to do make an image on the page of a random doggo. This API happens to do just that! So, let's make it happen. Make you file say:
71 |
72 | ```js
73 | const DOG_URL = "https://dog.ceo/api/breeds/image/random";
74 |
75 | const promise = fetch(DOG_URL);
76 | const doggos = document.querySelector(".doggos");
77 |
78 | promise
79 | .then(function(response) {
80 | const processingPromise = response.json();
81 | return processingPromise;
82 | })
83 | .then(function(processedResponse) {
84 | const img = document.createElement("img");
85 | img.src = processedResponse.message;
86 | img.alt = "Cute doggo";
87 | doggos.appendChild(img);
88 | });
89 | ```
90 |
91 | Here we create an `` tag and append it into the DOM via `appendChild`. Wouldn't it be cool if we could do it multiple times? Let's do it!!
92 |
93 | ```js
94 | const DOG_URL = "https://dog.ceo/api/breeds/image/random";
95 |
96 | const doggos = document.querySelector(".doggos");
97 |
98 | function addNewDoggo() {
99 | const promise = fetch(DOG_URL);
100 | promise
101 | .then(function(response) {
102 | const processingPromise = response.json();
103 | return processingPromise;
104 | })
105 | .then(function(processedResponse) {
106 | const img = document.createElement("img");
107 | img.src = processedResponse.message;
108 | img.alt = "Cute doggo";
109 | doggos.appendChild(img);
110 | });
111 | }
112 |
113 | document.querySelector(".add-doggo").addEventListener("click", addNewDoggo);
114 | ```
115 |
116 | Now you can add as many doggos as you want! Here's my example:
117 |
118 |
119 |
120 |
121 |
122 | For your extra-credit project, here are some cool ways to expand this project:
123 |
124 | 1. Add this to your GitHub in its own repo (we'll learn how to do that later)
125 | 1. Style it nice using CSS.
126 | 1. Show a loading gif (just use an ``) that shows when you're loading a new doggo and then hide it when you're done.
127 | 1. The dog.ceo API allows you to [request a list of breeds][breeds]. Use this list to populate a ``. Then when a user select a dog breed, show a picture of that dog using the the [random image by breed][pic] API.
128 |
129 | [dog]: https://dog.ceo/dog-api/
130 | [api]: https://github.com/toddmotto/public-apis
131 | [breeds]: https://dog.ceo/dog-api/documentation/
132 | [docs]: https://dog.ceo/dog-api/documentation/random
133 | [pic]: https://dog.ceo/dog-api/documentation/breed
134 |
--------------------------------------------------------------------------------
/lessons/calculator-setup.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 7
3 | title: "Calculator HTML & CSS Exercise"
4 | path: "/calculator-html"
5 | ---
6 |
7 | Our goal is to create a calculator that looks exactly like this image:
8 |
9 | 
10 |
11 | ## Exercise Files
12 |
13 | Download the calculator exercise files, including the beginning state, ending state, instructions, and specification for how the calculator should look:
14 |
15 | https://github.com/FrontendMasters/bootcamp/tree/master/static/exercises/5-github.zip
16 |
17 | We are focusing this lesson on creating the HTML and CSS for the caclulator. In a future lesson we will make it interactive with JavaScript.
18 |
19 | ## A few Things To Know About This Calculator:
20 |
21 | ### To Get Symbols for Math, You'll Need to Look Up Their HTML Codes
22 |
23 | One place to do that is here:
24 |
25 | [HTML Math Characters](https://www.toptal.com/designers/htmlarrows/math/)
26 |
27 | [HTML Arrow Characters](https://www.toptal.com/designers/htmlarrows/arrows/)
28 |
29 | ### The Calculator Buttons Should Be Clickable
30 |
31 | You'll program them later in the course with JavaScript. But for right now, somehow we need to code clickable buttons.
32 |
33 | ### Colors used in this design include:
34 |
35 | - black: #000000
36 | - white: #ffffff
37 | - light grey: #d8d9db
38 | - buttons on hover: #ebebeb
39 | - button active state: #bbbcbe
40 | - function buttons: #df974c
41 | - function buttons on hover: #dfb07e
42 | - function button active state: #dd8d37
43 |
44 | - The overall width of this calculator is 400px.
45 |
46 | ## Suggested approach:
47 |
48 | - Create a wrapper with a width of 400px to set up the calculator.
49 | - Determine how many rows and columns we need.
50 | - Identify elements that occupy more than one column.
51 | - Determine the HTML tags required to code rows and cells.
52 | - Code a single row of 4 elements to start with and see if you can get that working.
53 | - Now add the other rows of 4 elements.
54 | - Finally, add the rows where there are fewer than 4 elements. What do you need to adjust to get these to work?
55 | - Once your layout is mostly working, add the colors and make it pretty.
56 |
57 | ## HTML and CSS Tips and Hints
58 |
59 | - Programming is all about taking large problems and breaking them into smaller problems. If you're trying to tackle too much at once, break it into two smaller problems and try to solve one of those.
60 | - Personally, I wrote the HTML and CSS first. Once that's all taken care of, then I do the JavaScript.
61 | - For the font of the "result screen" I'd just use `monospace`.
62 | - There are so many ways to write this. There is no one right way. My solution is not the only nor is it the best solution. Experiment. Try. Fail. Succeed. It's all about learning here.
63 | - Good idea to use `` for the buttons. You have to deal with some extra styling stuff but it will make your code work pretty much automatically for disabled people. In general when writing HTML, if something serves the function of a button, make it a ``.
64 | - I used multiple rows of flex layed out divs for the button. You could do it all in one div using the `flex-wrap` property.
65 | - The secret to getting equal gutters (which is what you call the black space between buttons): you can set width to be `24.5%` (so four of them fit on a line) and then use `justify-cotent: space-between` to evenly space them. That'll give them a gutter of roughly `.5%` of the whole width. The problem with using percentages in conjuections with heights: your heights and widths are different. 5% of height is not the same of 5% of width, and that'll make the gutters look weird. You want the bottom gutters to be the same size as the side gutters. `margin-bottom` to the resuce! If you give the row a `margin-bottom` of `.5%` (if you're using my same numbers) then that'll work since margin is always measured as a function of width (just one of those things you have to know!) Hopefully that helps.
66 | - Sometimes I do the math to get things right. Sometimes I just guess-and-check to see if it looks okay.
67 | - You can add a class to get the orange buttons. Or you could try `:last-child` (assuming you have row div.)
68 |
69 | Good luck!
70 |
--------------------------------------------------------------------------------
/lessons/calculator.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 14
3 | title: "Exercise: Making the Calculator Work with JavaScript"
4 | path: "/calculator"
5 | ---
6 |
7 |
13 |
14 | We are going to rebuild the calculator on iOS! Here it is:
15 |
16 |
17 |
18 |
19 |
20 | My implementation of it is embedded here on the page so feel free to play with it.
21 |
22 | ## Let's go over the requirements:
23 |
24 | - The calculator should work like it does above
25 | - The calculator should function like a normal calculator
26 | - **Do not** implement `%` or `.`. You can assume everything will be an integer.
27 | - `C` means clear. When a user clicks it, it should clear everything and go back to the first state it was in when the page loaded.
28 | - Doing the back arrow is extra credit. It's like pressing backspace; it'll delete the last character typed. If it's clicked when there's only one digit, it sets the current number to be `0`.
29 | - Don't worry about if the number is too long for the screen.
30 | - Calculators tend to have some special behavior when you hit equals: if you type another number it erases the results and starts over. Feel free to do that but also free free (like me) to just treat it normally and make the user hit `C` if they want to clear it. Let's keep it simple.
31 |
32 | Okay, now that you have requirements, let's go over some tips and hints.
33 |
34 | ## JavaScript Tips and Hints
35 |
36 | - Again, no wrong way to do this. I wrote about 80 lines of JavaScript to finish the project (not including empty lines.) I say that so you have an idea of how much code you should be writing. If you're writing 200+ lines of code, you may want to rethink some of your solutions. Don't feel like you're going for the smallest possible answer. You're just going for correct.
37 | - I use `console.log` everywhere while I'm writing code. Just remember to take them out at the end.
38 | - Many small functions is _very_ preferable to one large function. Have each function do one thing well as opposed to having giant functions that do everything. If you find a function doing too, break it into smaller pieces. I solved it with eight different functions.
39 | - You'll need to keep track of several variables. Make sure these variables are stored in a place where they stay in scope.
40 | - You can add an event listener to each button individually, or you can use one listener at the root of the button. I did the latter but it's up to you.
41 |
42 | ## Types
43 |
44 | A brief note on what called **types** in JavaScript. We've danced the idea already and I want to make it a little more concrete for you. Strings, booleans, objects, arrays, numbers, these are different types of types (lol). JavaScript is a language where you don't have to concern yourself _a lot_ with types since it doesn't strictly enforce them (other languages do) but in this problem you are definitely going to have to deal with it.
45 |
46 | Whatever you put into the DOM and whatever you get out it are going to strings, every time. If I do:
47 |
48 |
49 |
50 | ```javascript
51 | const num = 10;
52 | const div = document.querySelector(".number-target"); // the div right above this block
53 | console.log(num, typeof num); // this is a number here
54 | div.innerText = num;
55 | console.log(div.innerText, typeof div.innerText); // it's a string here
56 | ```
57 |
58 | Since you're doing math here, you'll need the numbers to actually be of the number type. Otherwise you'll get `"5" + "5" = "55"`. There's a function called `parseInt(string)` that will turn a string of a number (`"5"`) to a number (`5`).
59 |
60 | You'll also see that we used the `typeof` operator. `typeof` tells whatever the type of the thing that comes right after it is. This is useful to quickly see what's happening in your code. Be careful because `typeof` is not always useful, but it is useful for telling numbers and strings apart.
61 |
62 | ## Starting HTML & CSS
63 |
64 | You can copy and paste the HTML & CSS to start with locally, or use our [calculcator starter CodePen][calcstarter] to focus on writing the JavaScript.
65 |
66 | - [The HTML][html] (you can view source on it)
67 | - [The CSS][css]
68 |
69 | **Now go code the JavaScript to make the calculator work!**
70 |
71 | ### Answer: [The JavaScript][js]
72 |
73 | [html]: https://github.com/FrontendMasters/bootcamp/blob/master/static/calculator.html
74 | [css]: https://github.com/FrontendMasters/bootcamp/blob/master/static/calculator.css
75 | [js]: https://github.com/FrontendMasters/bootcamp/blob/master/static/calculator.js
76 | [calcstarter]: https://codepen.io/frontendmasters/pen/wQMgWR
77 |
--------------------------------------------------------------------------------
/lessons/dogs.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Exercise: Dog App"
3 | path: "/dogs"
4 | order: 17
5 | ---
6 |
7 | We're going to build a dog picture viewer using the [dog.ceo API][dogceo]. This project is going to allow users to select a breed from a drop down list and then display a random picture of that breed.
8 |
9 | [Here's my version of it.][dog-viewer]
10 |
11 | Requirements:
12 |
13 | - Here are the API docs.
14 | - The list of breeds can be obtained by `List all breeds` API (see the docs linked above.) Request the list of breeds and then use those to create all the `option`s for the `select`.
15 | - When the page first loads, show a loading spinner until the image has loaded. I used an emoji with CSS animations to do so. Feel free to [look at what other people have done][loading], write your own (short tutorial will be below), or use an animated GIF. When the image loads, hide the spinner and show the image.
16 | - You already know how to change the `src` of an `img`, but if you immediately hide the loading spinner and show the `img`, you'll have a flash of time where nothing on the page since the image hasn't loaded yet. You can side step this by using `addEventListener` on the `img` tag and listen for the `"load"` event. Once the `"load"` event happens, it means the image is loaded and ready to be shown.
17 | - You can do AJAX request using fetch and promises like I showed you in the previous chapter. I'm now going to show you a brand new feature called async / await and it makes this a lot easier.
18 |
19 | Let's chat about CSS animations a second here:
20 |
21 | ```html
22 |
50 |
51 |
52 | ```
53 |
54 |
56 |
57 | - These `@keyframes` animations are re-usable animations that we define once and can use as many times as we want.
58 | - The second word (in our case `spin` and `psychadelic`) are what we called the animations, similar to a variable name. It's what we can refer to it as later.
59 | - Inside the `@keyframes` we have a `to` property. You can define very fine grain steps in the animation but here we want it to infer the steps. We _could_ add `from { transform: rotateZ(0deg); }` but the browser already knows that it's at `0deg` rotation. In this case, it just infers that you want it to start from where it is and animate to the `to` point.
60 | - You can also use percentages. Instead of `to` you'd use `100%` and instead of `from` you'd use `0%`. You can put as many steps as you want in there too e.g. `1%`, `10%`, `50%`, `92%`, etc.
61 | - Where you want to _use_ animation, put something like `animation: spin 1s infinite linear;`. This will use the `spin` animation we defined above, will take 1 second to do one iteration of the animation, will do it with linear easing, and will continue to do it infitiely. The order is not important here.
62 | - Easing allows you to make it seem elastic when it starts and stops, like a ball bouncing. It's faster at the bottom of the bounce and slower at the top.
63 |
64 | Let's talk about async / await for a second. So far we've been using promises and `.then`. There's an easier way to do it and it's called async / await.
65 |
66 | ```html
67 |
68 |
69 |
79 | ```
80 |
81 | Notice the function getDoggo has the `async` keyword there. This means inside of this function we can use `await`. `await` takes a promise and then _pauses_ the function until that promise resolves and gives you the answer back. It makes the code a lot simpler to understand. If you need to deal with errors, you can just try / catch. Feel free to write code this way for this exercise or continue using promises. Do note that I can't say `await` in the top level; it has to be inside of an async function.
82 |
83 | Your page does not have to look like mine. Feel free to design it however you want. Feel free to copy me too!
84 |
85 | Good luck!
86 |
87 | If you want to see my answers, [here is the JavaScript][js], [here is the CSS][css], and [here is the HTML][html].
88 |
89 | [dogceo]: https://dog.ceo/dog-api/documentation/
90 | [dog-viewer]: https://frontendmasters.github.io/bootcamp/dog-viewer/dog.html
91 | [loading]: https://codepen.io/tag/spinner/#
92 | [js]: https://github.com/btholt/bootcamp/blob/master/static/dog-viewer/dog.js
93 | [css]: https://github.com/btholt/bootcamp/blob/master/static/dog-viewer/dog.css
94 | [html]: https://github.com/btholt/bootcamp/blob/master/static/dog-viewer/dog.html
95 |
--------------------------------------------------------------------------------
/lessons/functions-and-scope.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 9
3 | title: "Functions and Scope"
4 | path: "/functions-and-scope"
5 | ---
6 |
7 | A function is a bit of re-usable code. Just how we like to re-use CSS classes, we love to re-use code. Let's start with an example:
8 |
9 | ```javascript
10 | function addTwo(number) {
11 | return number + 2;
12 | }
13 |
14 | const finalAnswer = addTwo(5);
15 | console.log(finalAnswer);
16 | ```
17 |
18 | This isn't super useful but hopefully it shows you the mechanics of how a function works. We created a function called `addTwo`. This function takes in one parameter, `number` and it returns that number with 2 added to it. We can now use that `addTwo` function as much as we want! Let's make a something a bit more useful.
19 |
20 | ```javascript
21 | function greet(firstName, lastName, honorific, greeting) {
22 | return `${greeting} ${honorific} ${lastName}! I’m extremely pleased you could join us, ${firstName}! I hope you enjoy your stay, ${honorific} ${lastName}.`;
23 | }
24 |
25 | console.log(greet("Brian", "Holt", "Lord", "Salutations"));
26 | console.log(greet("Jack", "Sparrow", "Captain", "A-hoy"));
27 | ```
28 |
29 | Now we rather than have to repeate ourselves over-and-over again with that long string, we can just call greet with the appropriate parameters. Here we use four parameters. The order is important that we send in the parameters because this will be the order function receives these parameters. You can have as many or as few parameters as you like.
30 |
31 | The way **call** a function is you add parens to the end of it, like this: `someFunctionName()`. If you see parens after a variable name, you instantly know that that's a function. Inside of the parens go the parameters. These variables will be passed to the function that is being called in the order that you put them there. Example:
32 |
33 | ```javascript
34 | const myHomeCity = "Salt Lake City";
35 | const myHomeState = "Utah";
36 | const myHomeCountry = "USA";
37 |
38 | function logOutYourHome(city, state, country) {
39 | console.log(`You are from ${city}, ${state} ${country}.`);
40 | }
41 |
42 | logOutYourHome(myHomeCity, myHomeState, myHomeCountry);
43 | ```
44 |
45 | ## Scope
46 |
47 | We'll talk about scope multiple times but we'll start off here with it. Every time you call a function, it has its own scope. Other things can't peek into it; it just has its own little workspace for it work with. Once its done, any variable that you haven't explicitly held on to or returned at the end is discarded. For example:
48 |
49 | ```javascript
50 | function addFive(number) {
51 | const someVariable = "you can't see me outside this function";
52 | return number + 5;
53 | }
54 |
55 | addFive(10);
56 | console.log(someVariable);
57 | ```
58 |
59 | This is not going to work. `someVariable` is inside of the `addFive` scope and once `addFive` completes, it throws `someVariable` away since it's now out-of-scope.
60 |
61 | ```javascript
62 | let friendsAtYourParty = 0;
63 | for (let i = 0; i <= 10; i++) {
64 | friendsAtYourParty++;
65 | }
66 | console.log(i);
67 | ```
68 |
69 | Even this doesn't work since `i` is only in scope for the loop and then after that it's thrown away. This can be a difficult one to deal with as someone new to coding because you'll go to log something or use a variable and it's out of scope so it's not there. Just know if that happens, this is probably the problem.
70 |
71 | Scope is hard. And scope is particularly strange in JavaScript (it varies by programming language.) If it feels hard it's because it is. A general, imperfect way for you to think about it right now is that a variable is "alive" (in scope) in between whatever the closest `{` is until that `{` closes its corresponding `}`. A few examples below, see if you can get it right. Keep in mind that the variable will stay in scope as long as any scope it exists in still exists. If I declare a variable in an outter scope and modify a variable in an inner scope, that variable will survive as long as the outter scope does. **It matters where the variable is declared.**
72 |
73 | ```js
74 | const A = "A";
75 | let F;
76 |
77 | function doStuff(B) {
78 | console.log(B);
79 | const C = "C";
80 | let H = "H";
81 | if (1 + 1 === 2) {
82 | const D = "D";
83 | H = "something else";
84 | }
85 | console.log(D);
86 | console.log(H);
87 | F = "F";
88 | }
89 |
90 | let E = 0;
91 | while (E < 3) {
92 | E++;
93 | console.log(A);
94 | const G = "G";
95 | }
96 | console.log(E);
97 | console.log(G);
98 |
99 | doStuff("B");
100 | console.log(B);
101 | console.log(C);
102 | console.log(F);
103 | ```
104 |
105 | This is pretty convulated example but see what you think. Once your ready, the next block will be the answers.
106 |
107 | ```javascript
108 | const A = "A";
109 | let F;
110 |
111 | function doStuff(B) {
112 | console.log(B); // works, B parameter is still in scope
113 | const C = "C";
114 | let H = "H";
115 | if (1 + 1 === 2) {
116 | const D = "D";
117 | H = "something else";
118 | }
119 | console.log(D); // does not work, D was declared in that if statement block
120 | console.log(H); // works, H was declared outside the if statement
121 | F = "F";
122 | }
123 |
124 | let E = 0;
125 | while (E < 3) {
126 | E++;
127 | console.log(A); // works, the outter block (called the global scope) is still in scope
128 | const G = "G";
129 | }
130 | console.log(E); // works, E was declared outside the whie loop
131 | console.log(G); // does not work, declared inside the while loop and it's over
132 |
133 | doStuff("B");
134 | console.log(B); // does not work, the B parameter expires after the function call
135 | console.log(C); // does not work, C was declared inside the function and the function is over
136 | console.log(F); // works, F was declared in the global scope
137 | ```
138 |
139 | ## Builtins
140 |
141 | Lots of functions already exist for you! Smart people have created this commonly-used functions for things we often need. For example, say you have a string and you want to make everything lowercase, you can do this:
142 |
143 | ```javascript
144 | const sentence = "ThIs HaS wEiRd CaSiNg On It";
145 | console.log(sentence.toLowerCase());
146 | ```
147 |
148 | Always be looking for the parens. And the best place to look all this stuff up is from our friends at Mozilla (makers of Firefox): [the MDN][mdn]. MDN used to stand for "Mozilla Developer Network" I think but now it's just synonmous with the documentation for the web. I literally look at this website several times a day. As I said before, you are not expected to remember everything. Looking things up on the MDN is **not** cheating.
149 |
150 | You can call `Math.round(5.1)` and it'll return that number rounded (in this, `5`). You can use `string.substr(indexToStart, howManyCharactersToInclude)` to return part of a string. For example `const name = "Brian Holt"; console.log(name.substr(6, 3))` logs out `"Hol"` (remember numbering starts at 0). We'll introduce them as we go but know there are a _lot_ of them. You'll learn by doing.
151 |
152 | ```javascript
153 | console.log(Math.round(5.1));
154 |
155 | const name = "Brian Holt";
156 | console.log(name.substr(6, 3));
157 | ```
158 |
159 | [mdn]: https://developer.mozilla.org/en-US/
160 |
--------------------------------------------------------------------------------
/lessons/github.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 6
3 | title: "GitHub"
4 | path: "/github"
5 | ---
6 |
7 | ## GitHub Pages
8 |
9 | ### Getting Web Pages Online
10 |
11 | Files are found at https://github.com/FrontendMasters/bootcamp/tree/master/static/exercises/5-github
12 |
13 | [Download ZIP of Files](https://github.com/FrontendMasters/bootcamp/blob/master/static/exercises/5-github.zip)
14 |
15 | ### Getting web pages online
16 |
17 | So far, the websites we've built have worked on the computer in front of us only. That's not much of a site if no one else can see it!
18 |
19 | You will need a way to display your web pages online so the world can see them. There are many ways to accomplish this. One of the oldest ways that still works great is the following:
20 |
21 | - **Sign up for web hosting** with a web hosting provider. (For the simple sites we're building, any web hosting provider will work!) This is also called a **server**.
22 | - As part of the hosting signup, **purchase a domain name** for your website. (Alternatively, if you already have a domain name, **point the domain name** to your new web hosting.)
23 | - Download a FTP program like **FileZilla** ([https://filezilla-project.org/download.php?type=client](https://filezilla-project.org/download.php?type=client)), and t**ransfer your website** from your computer to the web hosting provider's server.
24 | - **Look at your website!**
25 |
26 | Unfortunately, web hosting and domain names costs money, and we are just starting out, wanting to keep everything free.
27 |
28 | Fortunately, there is another solution to getting a simple website like ours online: GitHub Pages!
29 |
30 | You will need to follow the below instructions very carefully to get this working. I've included links to additional reading if you get lost along the way.
31 |
32 | ## 1. Sign up for GitHub
33 |
34 | First, sign up for GitHub.
35 |
36 | Go to [https://www.github.com](https://www.github.com) and sign up for the service.
37 |
38 | If you already have a GitHub account, make sure you are signed in.
39 |
40 | ## 2. Download GitHub Desktop
41 |
42 | Go to [https://desktop.github.com](https://desktop.github.com) and download the GitHub Desktop version for your computer, Mac or Windows.
43 |
44 | Install the application on your computer.
45 |
46 | ## 3. Create a repository
47 |
48 | A repository is a place where your files will be stored, similar to a folder or a directory.
49 |
50 | 1. Make sure you are signed into GitHub.
51 | 2. Go here: [https://github.com/new](https://github.com/new)
52 | 3. In the Repository Name field, enter your username.github.io. For example, I am `jen4web` on GitHub, so my repository name is `jen4web.github.io`. Add a description. The other settings should look like the ones below. Click the "create repository" button.
53 |
54 | 
55 |
56 | ## 4. Set up the repository in GitHub Desktop
57 |
58 | **Click the "Set up in Desktop" button in the next screen:**
59 |
60 | 
61 |
62 | Allow GitHub Desktop to open. There is an opening configuration screen. Click on "Sign into GitHub.com".
63 |
64 | 
65 |
66 | Enter your username (or email address) and password.
67 |
68 | 
69 |
70 | Configure your name and email as you wish, and click Continue. Click the finish button on the next screen, and you are good to go!
71 |
72 | Now you are in GitHub Desktop, and the screen should be filled out for you on the URL tab. Choose the desktop for your local path. It will create a new folder for you on the desktop:
73 |
74 | 
75 |
76 | Click the "Clone" button to finish setting up GitHub Desktop.
77 |
78 | ## 5. Make sure your GitHub folder has all of the files you want to post online
79 |
80 | Review the folder. Does it have all of your HTML, images, and CSS ready to post? If not, copy these files into the folder.
81 |
82 | **Make sure one file — probably your home page — is called index.html.** Make sure the links to that file are correct.
83 |
84 | Refer back to GitHub Desktop — once you've copied in your files and folders, you should see all of them listed here.
85 |
86 | 
87 |
88 | ## 6. Make a commit note for each file in the lower left corner
89 |
90 | A "commit" is the moment you upload these files and folders to GitHub. You are "committing" your changes to the repository.
91 |
92 | Make a note for each item by clicking on the file name and writing a note in the lower left corner of the screen.
93 |
94 | ## 7. Click the "Commit to master" button and "Publish Branch" button
95 |
96 | With notes in place, select all of your files and folders and click the blue "commit to master" button in the lower left. Then click the "publish branch" button in the black area in the upper right.
97 |
98 | ## 8. Look in your browser window
99 |
100 | Open a new tab in your browser and go to `https://.github.io` -- in my case, [https://jen4web.github.io](https://jen4web.github.io).
101 |
102 | You should see your web page, images, and CSS styles show up on your home page
103 |
104 | ## 9. Waaaa, it didn't work!!!
105 |
106 | What exactly "didn't work?"
107 |
108 | - Did you keep the exact same file and folder structure that you had on your computer previously? If not, you broke the paths between files, and you'll need to fix that.
109 | - Did all of your images and css upload? (Go to `www.github.com/`, click on Repositories, and click on the repository for this exercise. Are all of the files there and in the proper places?
110 | - Did you have a file called index.html? If not, you'll need to type in the name of that file as part of the URL. For example: [http://jen4web.github.io/about.html](http://jen4web.github.io/about.html)
111 | - Did you follow the above instructions exactly? If you named your repository something other than `.github.io`, it "won't work."
112 |
113 | ## 10. Updating files in your repository
114 |
115 | You may want to keep making changes to your website, and you want to keep publishing those changes to your repo. To do this:
116 |
117 | - Make all of your edits and changes in VSCode, just as you've been doing. Save your changes in the `.github.io` folder.
118 | - When you're ready to post your changes, open up GitHub Desktop, and go into the `.github.io repo`.
119 | - Make sure the "changes" tab is selected. It should show you all changed files since the last time you posted.
120 | - Select each file individually, make a note about what changed, and click "commit to master"
121 | - Click the button on the top right, which might now read "fetch origin" -- but it still does the same thing.
122 | - Check to see your changes in the browser.
123 |
124 | ## References
125 |
126 | - GitHub [http://www.github.com](http://www.github.com)
127 | - GitHub Pages [https://pages.github.com/](https://pages.github.com/)
128 | - How to Craft a Stand-Out Web Developer Portfolio
129 | [https://skillcrush.com/2016/10/31/web-developer-portfolio/](https://skillcrush.com/2016/10/31/web-developer-portfolio/)
130 | - How to Build an Impressive Portfolio When You're New to Tech
131 | [https://skillcrush.com/2015/03/12/impressive-tech-portfolio/](https://skillcrush.com/2015/03/12/impressive-tech-portfolio/)
132 |
133 | ## Your Portfolio Project
134 |
135 | When thinking about your portfolio, consider these business questions:
136 |
137 | - Who will see it?
138 | - What will they want to know about you?
139 | - What questions do you need to answer?
140 | - What value can you provide?
141 |
142 | Then consider these technical questions:
143 |
144 | - What is your color scheme? Branding?
145 | - Have you made the pages look consistent across your site?
146 | - Do all of your links work correctly?
147 | - Does your site look good in Chrome and Firefox?
148 |
149 | ### Waaaa, it "doesn't work"!!!
150 |
151 | Remember to use the HTML and CSS validators if things are looking odd in the browser, or if the colors in the editor seem off. That's an indicator that you've made some errors along the way. The HTML validator is great for catching errors pertaining to syntax, tag spelling, tag nesting, and applying the right attributes to a given tag. The CSS validator will find unclosed curly brackets, properties and values that don't exist, and more.
152 |
153 | HTML validator: http://validator.w3.org/
154 |
155 | CSS validator: http://jigsaw.w3.org/css-validator
156 |
--------------------------------------------------------------------------------
/lessons/images/FrontendMastersLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/lessons/images/FrontendMastersLogo.png
--------------------------------------------------------------------------------
/lessons/images/GitHub-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/lessons/images/GitHub-1.png
--------------------------------------------------------------------------------
/lessons/images/GitHub-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/lessons/images/GitHub-2.png
--------------------------------------------------------------------------------
/lessons/images/GitHub-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/lessons/images/GitHub-3.png
--------------------------------------------------------------------------------
/lessons/images/GitHub-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/lessons/images/GitHub-4.png
--------------------------------------------------------------------------------
/lessons/images/GitHub-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/lessons/images/GitHub-5.png
--------------------------------------------------------------------------------
/lessons/images/GitHub-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/lessons/images/GitHub-6.png
--------------------------------------------------------------------------------
/lessons/images/borderbox2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/lessons/images/borderbox2.png
--------------------------------------------------------------------------------
/lessons/images/brian.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/lessons/images/brian.jpg
--------------------------------------------------------------------------------
/lessons/images/contentbox1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/lessons/images/contentbox1.png
--------------------------------------------------------------------------------
/lessons/images/css-boxmodel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/lessons/images/css-boxmodel.png
--------------------------------------------------------------------------------
/lessons/images/css-shorthand.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/lessons/images/css-shorthand.png
--------------------------------------------------------------------------------
/lessons/images/jen.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/lessons/images/jen.jpg
--------------------------------------------------------------------------------
/lessons/images/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lessons/images/vscode-enabled.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/lessons/images/vscode-enabled.jpg
--------------------------------------------------------------------------------
/lessons/images/vscode-icon.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/lessons/images/vscode-icon.jpg
--------------------------------------------------------------------------------
/lessons/images/vscode-open-in-browser.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/lessons/images/vscode-open-in-browser.jpg
--------------------------------------------------------------------------------
/lessons/images/vscode-reload.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/lessons/images/vscode-reload.jpg
--------------------------------------------------------------------------------
/lessons/intro.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 0
3 | title: "Introduction to the Course"
4 | path: "/intro"
5 | ---
6 |
7 | From Jen Kramer and Brian Holt, your instructors:
8 |
9 | We are excited to teach you the basics of web development, including HTML, CSS, and some JavaScript. In this course we assume you know absolutely nothing about writing code.
10 |
11 | Because this is a short course, we are not able to cover everything about HTML, CSS, JavaScript, and web development exhaustively. Our goal is to teach you just enough to determine whether this kind of work for you. Do you enjoy it? Is it interesting?
12 |
13 | If so, you'll be ready to dig into all of the resources the Internet offers, learning more on your own. **Completing this course will not fully prepare you to be a professional web developer.** You will need more practice with these concepts and more education. However, this course is an excellent start towards that goal.
14 |
15 | ## Prerequisites
16 |
17 | We do assume that you have a basic grasp of how to operate your computer: how to browse the Internet, how to operate your operating system, how to use a keyboard and mouse, etc.
18 |
19 | We also assume you have completed the Internet Fundamentals course, a free introduction to important concepts like file management, the client and the server, and how the web works. http://www.internetfundamentals.com
20 |
21 | ## Tips to Succeed In This Course
22 |
23 | Contrary to what many people believe, you do not have to be a wizard with math to write code. The two subjects share some overlap but also are quite different. Many artists, lawyers, historians, linguists, and others have great success learning how to code. Don't let those preconceived notions hold you back at all.
24 |
25 | Also keep in mind that this is _hard_. Learning how to code is hard. It's similar to learning a foreign language where you have to learn a lot of small pieces of information to be able to make sense of the larger picture. It's easy to feel discouraged, especially when you feel like you _should_ get something but don't. Keep your head up and keep trying. Walk away from the problem and come back later. Try explaining your problem to someone / your dog / a [rubber ducky][rubber-duck] Seriously, it works. Say it out loud.
26 |
27 | Never feel afraid to Google _anything_. Every programmer you know, from the top person in the field to the newest student is Googling things _constantly_. This isn't cheating; it's a skill. It's a requirement. There is so much information coming at you that cannot possibly remember it all. Copy and paste code. Look at StackOverflow. Ask dumb questions. You get better by repeatedly exposing yourself to information. Each time a bit more will sink in.
28 |
29 | Don't try to understand every piece all at once. There are times where it's okay to just trust that something works and come back later to understand how. It's a tough balance because you do want to try to understand what's going on. We will tell you what's worth diving into and what's worth leaving for another day. You don't have to understand it all at once.
30 |
31 | Lastly, this isn't a get-rich-quick scheme. Learning to code is hard and requires a lot of hard work. While entry-level jobs are out there, and you can get them with months of work, we guarantee you you'll have to work hard for them.
32 |
33 | ## Who Are We?
34 |
35 | ### Jen Kramer, Lecturer at Harvard University Extension School
36 |
37 | 
38 |
39 | I'm Jen Kramer. I teach the web!
40 |
41 | For most of my 18 year career, I've been a freelancer. I lived in the backwoods of Vermont and built websites for interesting people. I ran a small web design firm in New Hampshire and built websites for interesting companies. Now I live in the Boston suburbs, and while I build fewer sites than I used to do, I do still occasionally put together sites for a good cause.
42 |
43 | Throughout, I've also been a teacher. I taught academically: community college, undergraduates, and graduate students. I taught commercially: LinkedIn Learning/Lynda.com, Frontend Masters, osTraining, and O'Reilly, creating over 35 video training courses. I taught dozens of workshops for corporations and at conferences. I've presented at a conference every six weeks, on average, for the last ten years. And I've written 3 books -- currently working on #4.
44 |
45 | Most of my teaching focuses on the continuum from concept for a website through coding the front end. That includes topics like user experience (UX), user interface design (UI), HTML, CSS, responsive design, content management systems like Joomla and WordPress, project management, web marketing and branding, web semantics, web analytics, and accessibility.
46 |
47 | In all my years of teaching, my favorite audience is the beginning beginners -- in other words, people just like you. You are the most difficult audience, because concepts professionals have long taken for granted are brand new and fresh for you. Everything needs to be explained exactly. In explaining, I learn what I didn't know in enough detail before. It is here that the habits of an entire career are formed. It is here, I believe, that I can most influence the web and where it's going.
48 |
49 | [frontend-masters]: https://frontendmasters.com/teachers/jen-kramer/
50 | [twitter]: https://twitter.com/jen4web
51 | [facebook]: https://www.facebook.com/webdesignjen/
52 | [github]: https://github.com/jen4web
53 | [linkedin]: https://www.linkedin.com/in/jen4web/
54 | [slideshare]: https://www.slideshare.net/jen4web
55 |
56 | ### Brian Holt, Cloud Developer Advocate at Microsoft
57 |
58 | 
59 |
60 | My name is Brian Holt. I'm presently (as of writing) a cloud developer advocate at Microsoft. That means I talk to people why I think Azure is a pretty cool place to deploy your code. I write a lot of code demos and help with some open source libraries. I've taught a lot of lessons on [Frontend Masters][frontend-masters] and used to be on the frontend development podcast [Front End Happy Hour][fehh]. Previous to that, I was a senior or staff JavaScript and Node engineer at LinkedIn, Netflix, Reddit, Needle, KSL.com, and NuSkin.
61 |
62 | My biggest passions in life are people and experiences. I hope by going through this course that it can improve your life in some meaningful way and that you in turn can improve someone else's life. My beautiful wife and I live in Seattle, Washington in the United States of America with our cute little Havanese dog Luna. I'd almost always rather be traveling and have been fortunate to see over thirty countries in the past five years.
63 |
64 | Please catch up with me on social media, would love to chat:
65 |
66 | - [Twitter][twitter]
67 | - [Instagram][instagram]
68 | - [GitHub][github]
69 | - [LinkedIn][linkedin]
70 |
71 | I love to teach. It's a challenging task that forces you to peel back all the knowledge you've gain so you can approach someone who lacks the same experience and terminology you have. It forces you to take amorphous concepts floating in your brain and crystalize them into solid concepts that you can describe. It forces you to acknowledge your gaps in knowledge because you'll begin to question things you know others will question. For me to ever master a concept, I have to teach it to someone else.
72 |
73 | Unfortunately life gets in the way. These courses take dozens of hours to prepare and to get right. While I'd love to just create content all day, I have a (awesome) day job at Microsoft that demands and deserves my full attention. However I'm grateful to the team at [Frontend Masters][fem] for giving me deadlines and incentive to create these courses and then allowing and encouraging me to open source the materials. Not everyone has the money to pay for these courses which is why these materials are and will be forever open source for you to reference and share. I think the video content is pretty good too and so I'd encourage you to take a look at that on Frontend Masters too if that's in the cards for you.
74 |
75 | [rubber-duck]: https://en.wikipedia.org/wiki/Rubber_duck_debugging
76 | [frontend-masters]: https://frontendmasters.com/teachers/brian-holt/
77 | [fehh]: http://frontendhappyhour.com/
78 | [fem]: https://frontendmasters.com/
79 | [twitter]: https://twitter.com/holtbt
80 | [instagram]: https://www.instagram.com/briantholt/
81 | [github]: https://github.com/btholt
82 | [linkedin]: https://www.linkedin.com/in/btholt/
83 |
84 | ## Why was this course created?
85 |
86 | 
87 |
88 | Frontend Masters sponsored this bootcamp as a service to their community. They have long been the leader in advanced front-end web development courses, well-respected by the professional community. However, increasingly, they were contacted by beginners, attracted to the high quality of the courses, but without the background to adequately take advantage of the material.
89 |
--------------------------------------------------------------------------------
/lessons/mole.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 18
3 | title: "Exercise: Feed-A-Star-Mole"
4 | path: "/mole"
5 | ---
6 |
7 | Here's your next project, a fun variant on the game Whack-A-Mole. If you're not familiar with the premise, the idea is that little moles will pop out of holes and the game is to tap them before they go back in their holes. In our variant, they're hungry little star moles and we're going to feed them worms! After a user gets 10 points, they win the game! There are also more-rare royal star moles that are worth double. If a user doesn't click on a mole in time, the mole frowns and heads back in its hole. If you manage to feed it in time, it smiles happily and disappers back into its hole.
8 |
9 | We even have beautiful artwork for you to use, drawn by the talented [Alice Brereton][alice].
10 |
11 | [Here's my version of the game.][mole]
12 |
13 | This is a hard project but you can do it! I'd recommend taking it in steps rather than trying to do everything at once. Some sort of progression. I'd recommend something like:
14 |
15 | - Get all the CSS and HTML on the page. Have ten holes with a hungry mole in each. No JS done yet.
16 | - Make the moles show up and disappear (don't worry about the sad face / butt yet.) Don't make them clickable yet, just have them disappear and reappear after a random interval.
17 | - Make the hungry moles clickable. If you click on one, add 1 point to your score.
18 | - After 10 clicks, show the win screen.
19 | - Show the worm meter. As a player clicks on moles, show more and more of the worm.
20 | - Make one in ten of the moles that show up a royal mole. If a user clicks a royal mole, add 2 points to their score.
21 | - If a user doesn't click a mole in time, show a sad mole.
22 | - If a user does click a mole in time, show a fed mole.
23 | - After both sad and fed moles, show a mole butt.
24 | - You're done!
25 |
26 | Feel free to play with the timing. In my version I used the following timings:
27 |
28 | - Hungry moles show up for two seconds
29 | - Sad, fed, and mole butts show for a half second.
30 | - Moles wait at least two seconds before showing up in the same hole and no more than twenty seconds.
31 |
32 | Some concepts you'll need to know.
33 |
34 | - `Date.now()` is going to be a useful function for you. It gives you back how many milliseconds have transpired since January 1, 1970 (often to referred as UNIX time or UNIX Epoch time, [see here if you want to know more][epoch]).
35 |
36 | ```javascript
37 | console.log(Date.now());
38 | ```
39 |
40 | - You can handle the timing one of two ways: `setInterval` or `requestAnimationFrame`
41 | - `setInterval` allows you to run a function every X milliseconds. So if I wrote `setInterval(function() { console.log('hi') }, 1000);` would log `hi` every second.
42 | - `requestAnimationFrame` is preferred. It asks the browser once it's finished doing the previous render to call you function. This happens quite frequently (on the order of milliseconds) so be aware of that. The nice thing is that requestAnimationFrame doesn't run while the browser tab isn't in focus.
43 |
44 | ```html
45 |
setInterval 0
46 |
requestAnimationFrame 0
47 |
69 | ```
70 |
71 | - The latter is a bit more complicated with `requestAnimationFrame` but it allows the browser to yield back to you when its idle. The former will run no matter after the allotted amount of milliseconds.
72 | - Notice with `requestAnimationFrame`, I'm checking after `Date.now() + 1000` milliseconds have gone by. This is how you make it run only every second.
73 | - You'll probably want to represent each mole as an object. You'll need to keep track of what state each mole is in ("fed", "hungry", "leaving", "sad", "gone"), if it's a royal or not, and the time to update its status again.
74 | - Statuses flow predictably. "gone" goes to "hungry" next, "hungry" goes to "sad", "sad" goes to "leaving", and "leaving" to "gone", always. "hungry" can go to "fed" if they're clicked in time. They go from "fed" to "leaving" and then back into the normal cycle.
75 | - You can modify the `src` of an image and it updates the image.
76 |
77 | ```html
78 |
79 |
98 | ```
99 |
100 | You'll need all the static assets (images.) [Grab them here.][assets]
101 |
102 | Good luck!
103 |
104 | If you want to see my answers, [here is the JavaScript][js], [here is the CSS][css], and [here is the HTML][html].
105 |
106 | [alice]: https://www.pickledalice.com/
107 | [mole]: ./mole-game/mole.html
108 | [epoch]: https://en.wikipedia.org/wiki/Unix_time
109 | [assets]: https://frontendmasters.github.io/bootcamp/mole.zip
110 | [js]: https://github.com/btholt/bootcamp/blob/master/static/mole-game/mole.js
111 | [css]: https://github.com/btholt/bootcamp/blob/master/static/mole-game/mole.css
112 | [html]: https://github.com/btholt/bootcamp/blob/master/static/mole-game/mole.html
113 |
--------------------------------------------------------------------------------
/lessons/quiz.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 10
3 | title: "Exercise: Quiz"
4 | path: "/quiz"
5 | ---
6 |
7 | For your first exercise you are going to build a quiz game! We are going to use a tool called [CodePen][codepen]. CodePen is basically a little miniature development environment contained in your browser. Instead of having your separate HTML, CSS, and JavaScript files, CodePen combines them nicely into one web page for you. It's nice for making simple, shareable pieces of code. And you it makes it easy to do exercises.
8 |
9 | Some words of advice for as you use CodePen:
10 |
11 | - I recommend signing up for an account. But you do not have to. This will allow you to save your work.
12 | - The way you'll be able to save your work is click the **Fork** button. It means to fork (as in how a river forks) from the original author's version to your own version. You can modify it without worrying about changing mine. It's making your own copy.
13 | - It is possible to crash the browser. Normally CodePen can recover well on its own but in the case that you make it crash so bad it can't even start, see this [blog post][no-js] to see how to start with JavaScript turned off.
14 | - In this exercise you do not need to modify the CSS or HTML at all. However you can see it and play around it if you want to.
15 | - The first one is complete for you as an example. You don't need to change anything about it.
16 | - If you see see a icon like this: ! in the bottom right of the JavaScript pane, it means you have syntax errors in your JS (code that doesn't work / make sense.) If you click on it, it will show you what's wrong. If you're writing code and nothing is happening differently, check to see if that exclamation point is there.
17 | - If you're stuck, Google it. That's not cheating. That's what you're supposed to do.
18 | - Don't be afraid of looking at the answers. This is about learning, not grades. That said, don't cheat yourself. Try. Struggle. Learn.
19 |
20 | Good luck!
21 |
22 | - [Exercise][ex]
23 | - [Answer][ans]
24 |
25 | [codepen]: https://codepen.io
26 | [no-js]: https://blog.codepen.io/documentation/features/turn-off-javascript-in-previews/
27 | [ex]: https://codepen.io/btholt/pen/VELvwP
28 | [ans]: https://codepen.io/btholt/pen/aRZWGV
29 |
--------------------------------------------------------------------------------
/lessons/setup.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 1
3 | title: "Setup & Prerequisites"
4 | path: "/setup"
5 | ---
6 |
7 | ## 1. Go Through Internet Fundamentals
8 |
9 | In order to make sure you have the skills you’ll need to follow along with the Bootcamp, you'll need to take the FREE [Internet Fundamentals course](https://internetfundamentals.com).
10 |
11 | ## 2. Install Visual Studio Code (VSCode)
12 |
13 | You should install [VSCode](https://code.visualstudio.com) (Visual Studio Code) on your computer, as
14 | this was part of the Internet Fundamentals course:
15 | www.internetfundamentals.com
16 |
17 | To this, we will add an extension.
18 |
19 | 1\. Open VSCode. On the left side of the window, click on the very last
20 | icon:
21 |
22 |
23 |
24 | 2\. In the Search box, type in **Open in Browser** and hit return. You
25 | should see a list of a bunch of extensions called Open in Browser.
26 |
27 | 3\. The very first one, or one near the top of the list, should be the
28 | version from TechER. Click the green Install button.
29 |
30 | 
31 |
32 | Once installed, this will change to a blue Reload button. Click that,
33 | and the extension will be installed.
34 |
35 | 
36 |
37 | The extension is installed when your screen looks like this:
38 |
39 | 
40 |
--------------------------------------------------------------------------------
/lessons/tests.md:
--------------------------------------------------------------------------------
1 | ---
2 | order: 12
3 | title: "Exercise: Make the Tests Pass"
4 | path: "/tests"
5 | ---
6 |
7 | As a way of making sure your code doesn't break over time, we write testing code to test our code. That would like something like this: `expect(addTwo(5)).toEqual(7)`. As long as your tests pass, you can deploy new code with confidence that you didn't break old things in the process of launching new code. It's a failsafe of sorts.
8 |
9 | In this exercise, I wrote a bunch of tests that you need to make pass. You will not need to write any HTML or CSS. In the preview window, you'll see a summary of how many tests you have made pass and how many are still failing. The best approach here is to tackle each test one-at-a-time and ignore the others. You can even make other tests not run by changing the test-calling functions to be `xdescribe` or `xit` or you can only one test/suite run by changing them to `fdescribe` or `fit`, just remember to change them all back to `it` and `describe`.
10 |
11 | These tests are hard. Be prepared for that. You're finished when you make all your tests pass.
12 |
13 | The sorting one is particularly tough. If you need help, check out [my other course here][cs] and scroll down to the bubble sort part.
14 |
15 | - [Exercise][exercise]
16 | - [Answer][answer]
17 |
18 | [exercise]: https://codepen.io/btholt/pen/QZKxRw?editors=0010
19 | [answer]: https://codepen.io/btholt/pen/xyEajx?editors=0010
20 | [cs]: https://btholt.github.io/four-semesters-of-cs/
21 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bootcamp",
3 | "description": "Frontend Masters Boot Camp",
4 | "version": "1.0.0",
5 | "author": "Brian Holt ",
6 | "dependencies": {
7 | "bootstrap": "^4.3.1",
8 | "code-mirror-themes": "^1.0.0",
9 | "gatsby": "^2.0.9",
10 | "gatsby-cli": "^2.4.1",
11 | "gatsby-link": "^2.0.1",
12 | "gatsby-plugin-klipse": "^2.1.0",
13 | "gatsby-plugin-layout": "^1.0.2",
14 | "gatsby-plugin-react-helmet": "^3.0.0",
15 | "gatsby-plugin-remove-trailing-slashes": "^2.0.4",
16 | "gatsby-plugin-sharp": "^2.0.5",
17 | "gatsby-remark-autolink-headers": "^2.0.6",
18 | "gatsby-remark-copy-linked-files": "^2.0.5",
19 | "gatsby-remark-images": "^2.0.1",
20 | "gatsby-remark-prismjs": "^3.0.0",
21 | "gatsby-source-filesystem": "^2.0.1",
22 | "gatsby-transformer-remark": "^2.1.3",
23 | "prismjs": "^1.15.0",
24 | "react": "^16.5.2",
25 | "react-dom": "^16.5.2",
26 | "react-helmet": "^5.2.0"
27 | },
28 | "keywords": [],
29 | "license": "(CC-BY-NC-4.0 OR Apache-2.0)",
30 | "main": "n/a",
31 | "scripts": {
32 | "build:static": "gatsby build --prefix-paths",
33 | "build:zip:fox": "bestzip static/fox.zip static/fox-pet/",
34 | "build:zip:mole": "bestzip static/mole.zip static/mole-game/",
35 | "build:zip:luna": "bestzip static/luna.zip static/gallery/images/",
36 | "build:zip": "run-p build:zip:mole build:zip:fox build:zip:luna",
37 | "build": "run-s build:zip build:static",
38 | "dev": "gatsby develop",
39 | "format": "prettier --write \"src/**/*.{js,jsx,md,css}\"",
40 | "lint": "eslint \"src/**/*.{js,jsx}\""
41 | },
42 | "devDependencies": {
43 | "@babel/polyfill": "^7.0.0",
44 | "babel-eslint": "^10.0.1",
45 | "bestzip": "^2.1.1",
46 | "core-js": "^2.5.7",
47 | "eslint": "^5.6.0",
48 | "eslint-config-prettier": "^3.1.0",
49 | "eslint-plugin-import": "^2.14.0",
50 | "eslint-plugin-jsx-a11y": "^6.1.1",
51 | "eslint-plugin-react": "^7.11.1",
52 | "npm-run-all": "^4.1.5",
53 | "prettier": "^1.14.3"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/components/TOCCard.css:
--------------------------------------------------------------------------------
1 | .main-card {
2 | width: 100%;
3 | margin: 0;
4 | overflow: hidden;
5 | background-color: white;
6 | background-image: url(https://frontendmasters.github.io/bootcamp/layout/postIT_bg.png);
7 | background-size: 60px;
8 | box-shadow: 0px 10px rgba(36, 40, 39, 0.5);
9 | padding: 20px;
10 | }
11 |
12 | .lesson-title {
13 | font-size: 32px;
14 | padding: 25px 30px 2px 30px;
15 | font-family: "PosterizerKGRough", "Courier New", Courier, monospace;
16 | color: #2c2825;
17 | text-align: center;
18 | }
19 |
20 | .lesson-content {
21 | padding: 0 0 15px 0;
22 | color: #2c2825;
23 | overflow: hidden;
24 | }
25 |
26 | @media (min-width: 680px) {
27 | .lesson-content {
28 | padding-right: 15px;
29 | }
30 | }
31 |
32 | .lesson-content a {
33 | color: #923a21;
34 | padding-left: 0;
35 | }
36 |
--------------------------------------------------------------------------------
/src/components/TOCCard.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Link from "gatsby-link";
3 |
4 | import "./TOCCard.css";
5 |
6 | const LessonCard = ({ content, title }) => (
7 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/static/doggos/doggos.js:
--------------------------------------------------------------------------------
1 | const DOG_URL = "https://dog.ceo/api/breeds/image/random";
2 |
3 | const doggos = document.querySelector(".doggos");
4 |
5 | function addNewDoggo() {
6 | const promise = fetch(DOG_URL);
7 | promise
8 | .then(function(response) {
9 | const processingPromise = response.json();
10 | return processingPromise;
11 | })
12 | .then(function(processedResponse) {
13 | const img = document.createElement("img");
14 | img.src = processedResponse.message;
15 | img.alt = "Cute doggo";
16 | doggos.appendChild(img);
17 | });
18 | }
19 |
20 | document.querySelector(".add-doggo").addEventListener("click", addNewDoggo);
21 |
--------------------------------------------------------------------------------
/static/exercises/1-html/book excerpt.txt:
--------------------------------------------------------------------------------
1 | I. What It's All About
2 |
3 | Whence come the thousands of photographs used every month by newspapers and magazines?
4 |
5 | More than that, whence do the photographs come which are used by makers of calendars, postcards, for advertisements, and for illustrating books, stories and articles?
6 | ---------------------------------
7 | This little book is a practical, up-to-the-minute answer to the question: "How can I make my camera-work profitable?"
8 |
9 | A. H. Beardsley,
10 | Publisher, Photo-Era Magazine.
11 | ----------------------------------
12 |
13 | At first thought, the answer is, "From professional photographers and publisher-photo-services." But professional photographers do not produce one-third of the photographs used, and publisher-photo-services are supplied by that same large number of camerists that supply publications with most of their prints.
14 |
15 | No one can deny that the greatest number of prints published are bought from amateur photographers in towns no larger than the average, and sometimes smaller.
16 |
17 | The camerist does not have to get in an air-ship and fly to Africa in order to produce photographs that will sell. Read what Waldon Fawcett says, himself a success at selling his photographs:
18 |
19 | "The photographer is apt to think that all his ambitions would be realised if only he could journey to foreign shores or to distant corners of our country; or if he could attend the spectacular events that focus the attention of the world now and then. [emphasize] This is a delusion. The real triumph is that of the photographer who utilises the material ready at hand in his own district, be it large or small."[end]
20 |
21 | And more, a person does not have to be an expert photographer in order to succeed at the work. Here is what one prominent writer says about it:
22 |
23 | "The requirements of the field are well within the capabilities of even the beginner in photography, viz.; the ability to make good negatives and good prints, the ability to recognise news-value, and a methodical plan to find the market where the prints will find acceptance. The man or woman who can meet these requirements should be fairly successful from the beginning, and will open up quickly new avenues of special work and profit."
24 |
25 | In short, ability to make metaphors, create lovely heroines or such is not at all necessary to the successful selling of photographs to publications.
26 |
27 | Is the field overcrowded? [emphasis]No.[end] If there were ten times as many persons engaged in the work they could all keep themselves busy.
28 |
29 | The field—how wide is it? Get out your map of the world. The field for [emphasis]making [end] photographs extends from the top margin to the bottom, and from the left to the right. The field for [emphasis]selling [end] photographs—which is more to the point—extends over about five thousand publications which use prints; not to speak of a few score of other markets.
30 |
31 | The markets may be classified briefly:
32 |
33 | (1) Newspapers
34 | (2) Magazines
35 | (3) Postcard-makers
36 | (4) Calendar-makers
37 | (5) Art-study producers
38 | (6) Illustrations for books
39 | (7) Illustrations for articles
40 | (8) Prints for advertising.
41 |
42 | And there are more, of more specialised branches.
43 |
44 | And how does it pay? Please note: "A certain magazine once paid $100 for four prints of sundials. An amateur, who happened to be on the spot with a kodak, made over $200 out of a head-on railroad-collision. A New York professional netted $125 from the newspaper-use of a wedding-party, of considerable local prominence, which was leaving the church after the ceremony." One amateur "realised $300 a year for two or three years from a lucky snapshot of eight pet rabbits in a row."
45 |
46 | A set of South-Pole photographs brought $3,000 from Leslie's and $1,000 more from the International Feature Service. These all, though, are very exceptional instances. The average print sells for about three dollars. But there is absolutely nothing in the world to hinder a wide-awake person with a camera from making from several hundred to over $3,000 a year from his prints. If he becomes a specialist he may earn as high as $5,000 or even more.
47 |
48 | No discrimination is made between press-photographers. The person wins who "delivers the goods."
49 |
50 | However, I do not mean that the instances of $200 or so for prints should be taken as the prices ordinarily paid. I do not maintain that there is a fortune awaiting the man with the camera; but I do say there are unlimited possibilities for salable photographs and almost an unlimited number of markets for them. But there are not "barrels of money" in it, for all. A person may add appreciably to his income for having sold photographs; and having developed the trade to a high degree, he may cash cheques to the amount of $5,000 or more a year. But not every one. Just some. And it isn't like the log and the falling off it. It's work—hard work—[emphasis]hard work.[end]
51 |
52 | Success at selling press-photographs does not depend on the size of the town you live in, the cost or manufacture of your apparatus, or on your literary ability. It depends on you and your worship of the homaged gods of success if you would sell photographs. The gift of these gods is the ability to make good.
53 |
54 | --------------------------------------
55 | An excerpt from the book, "Making Your Camera Pay," by Frederick C. Davis. Copyright 1922, Robert M. McBride & Company, New York. Full book available online at Project Gutenberg (link to https://www.gutenberg.org/files/35709/35709-h/35709-h.htm)
--------------------------------------------------------------------------------
/static/exercises/1-html/book.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
What It's All About
11 |
12 |
Whence come the thousands of photographs used every month by newspapers and magazines?
13 |
14 |
More than that, whence do the photographs come which are used by makers of calendars, postcards, for advertisements, and for illustrating books, stories and articles?
15 |
16 |
This little book is a practical, up-to-the-minute answer to the question: "How can I make my camera-work profitable?"
17 |
18 | A. H. Beardsley,
19 | Publisher, Photo-Era Magazine.
20 |
21 |
22 |
At first thought, the answer is, "From professional photographers and publisher-photo-services." But professional photographers do not produce one-third of the photographs used, and publisher-photo-services are supplied by that same large number of camerists that supply publications with most of their prints.
23 |
24 |
No one can deny that the greatest number of prints published are bought from amateur photographers in towns no larger than the average, and sometimes smaller.
25 |
26 |
The camerist does not have to get in an air-ship and fly to Africa in order to produce photographs that will sell. Read what Waldon Fawcett says, himself a success at selling his photographs:
27 |
28 |
29 |
"The photographer is apt to think that all his ambitions would be realised if only he could journey to foreign shores or to distant corners of our country; or if he could attend the spectacular events that focus the attention of the world now and then. This is a delusion. The real triumph is that of the photographer who utilises the material ready at hand in his own district, be it large or small."
30 |
31 |
32 |
And more, a person does not have to be an expert photographer in order to succeed at the work. Here is what one prominent writer says about it:
33 |
34 |
35 |
"The requirements of the field are well within the capabilities of even the beginner in photography, viz.; the ability to make good negatives and good prints, the ability to recognise news-value, and a methodical plan to find the market where the prints will find acceptance. The man or woman who can meet these requirements should be fairly successful from the beginning, and will open up quickly new avenues of special work and profit."
36 |
37 |
38 |
In short, ability to make metaphors, create lovely heroines or such is not at all necessary to the successful selling of photographs to publications.
39 |
40 |
Is the field overcrowded? No. If there were ten times as many persons engaged in the work they could all keep themselves busy.
41 |
42 |
The field—how wide is it? Get out your map of the world. The field for making photographs extends from the top margin to the bottom, and from the left to the right. The field for selling photographs—which is more to the point—extends over about five thousand publications which use prints; not to speak of a few score of other markets.
43 |
44 |
The markets may be classified briefly:
45 |
46 |
Newspapers
47 |
Magazines
48 |
Postcard-makers
49 |
Calendar-makers
50 |
Art-study producers
51 |
Illustrations for books
52 |
Illustrations for articles
53 |
Prints for advertising.
54 |
55 |
56 |
And there are more, of more specialised branches.
57 |
58 |
And how does it pay? Please note: "A certain magazine once paid $100 for four prints of sundials. An amateur, who happened to be on the spot with a kodak, made over $200 out of a head-on railroad-collision. A New York professional netted $125 from the newspaper-use of a wedding-party, of considerable local prominence, which was leaving the church after the ceremony." One amateur "realised $300 a year for two or three years from a lucky snapshot of eight pet rabbits in a row."
59 |
60 |
A set of South-Pole photographs brought $3,000 from Leslie's and $1,000 more from the International Feature Service. These all, though, are very exceptional instances. The average print sells for about three dollars. But there is absolutely nothing in the world to hinder a wide-awake person with a camera from making from several hundred to over $3,000 a year from his prints. If he becomes a specialist he may earn as high as $5,000 or even more.
61 |
62 |
No discrimination is made between press-photographers. The person wins who "delivers the goods."
63 |
64 |
However, I do not mean that the instances of $200 or so for prints should be taken as the prices ordinarily paid. I do not maintain that there is a fortune awaiting the man with the camera; but I do say there are unlimited possibilities for salable photographs and almost an unlimited number of markets for them. But there are not "barrels of money" in it, for all. A person may add appreciably to his income for having sold photographs; and having developed the trade to a high degree, he may cash cheques to the amount of $5,000 or more a year. But not every one. Just some. And it isn't like the log and the falling off it. It's work—hard work—hard work.
65 |
66 |
Success at selling press-photographs does not depend on the size of the town you live in, the cost or manufacture of your apparatus, or on your literary ability. It depends on you and your worship of the homaged gods of success if you would sell photographs. The gift of these gods is the ability to make good.
Hello, world! My name is Jen. I live in Boston. Minneapolis is awesome. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam nostrum, ea consequatur quae impedit sunt cupiditate amet at saepe nulla consequuntur tenetur, repellendus commodi voluptates molestiae deserunt fugit? Consequuntur odit rem magni, veritatis distinctio unde. Tempore ad expedita fugit suscipit.
13 |
14 |
15 |
It's hard to make it easy, but it's easy to make it hard.
16 | Jen Kramer
17 |
18 |
19 |
Here is a picture of a kitten. Because my page is boring without a photo.
20 |
21 |
22 |
23 |
Make a Peanut Butter and Jelly Sandwich
24 |
25 |
Get some peanut butter, jelly, and 2 pieces of bread.
26 |
Spread peanut butter on one piece of bread and jelly on the other.
27 |
Put the peanut butter and jelly together, with the bread side facing out.
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Quasi maiores voluptates cum quis maxime blanditiis asperiores tempore totam ipsam dignissimos? Dolorem dolores illo dignissimos quasi facilis cupiditate, natus obcaecati error quaerat. Corporis ipsa maxime, soluta hic veniam unde ex rem illum ipsam!
41 |
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Quasi maiores voluptates cum quis maxime blanditiis asperiores tempore totam ipsam dignissimos? Dolorem dolores illo dignissimos quasi facilis cupiditate, natus obcaecati error quaerat. Corporis ipsa maxime, soluta hic veniam unde ex rem illum ipsam!
42 |
43 |
More Blah Blah Detail
44 |
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Quasi maiores voluptates cum quis maxime blanditiis asperiores tempore totam ipsam dignissimos? Dolorem dolores illo dignissimos quasi facilis cupiditate, natus obcaecati error quaerat. Corporis ipsa maxime, soluta hic veniam unde ex rem illum ipsam!
45 |
Lorem ipsum dolor sit amet consectetur adipisicing elit. Illo reiciendis ut explicabo sint repudiandae eligendi culpa laboriosam exercitationem! Inventore tenetur doloremque quaerat illo aspernatur sunt aperiam, nam temporibus veritatis cum vel corporis repellendus eveniet optio mollitia ab voluptates consequatur perspiciatis quasi atque? Rerum architecto nobis dicta laudantium neque, accusantium sapiente.
Hello, world! My name is Jen. I live in Boston. Minneapolis is awesome. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam nostrum, ea consequatur quae impedit sunt cupiditate amet at saepe nulla consequuntur tenetur, repellendus commodi voluptates molestiae deserunt fugit? Consequuntur odit rem magni, veritatis distinctio unde. Tempore ad expedita fugit suscipit.
20 |
21 |
22 |
It's hard to make it easy, but it's easy to make it hard.
23 | Jen Kramer
24 |
25 |
26 |
Here is a picture of a kitten. Because my page is boring without a photo.
27 |
28 |
29 |
30 |
Make a Peanut Butter and Jelly Sandwich
31 |
32 |
Get some peanut butter, jelly, and 2 pieces of bread.
33 |
Spread peanut butter on one piece of bread and jelly on the other.
34 |
Put the peanut butter and jelly together, with the bread side facing out.
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Quasi maiores voluptates cum quis maxime blanditiis asperiores tempore totam ipsam dignissimos? Dolorem dolores illo dignissimos quasi facilis cupiditate, natus obcaecati error quaerat. Corporis ipsa maxime, soluta hic veniam unde ex rem illum ipsam!
48 |
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Quasi maiores voluptates cum quis maxime blanditiis asperiores tempore totam ipsam dignissimos? Dolorem dolores illo dignissimos quasi facilis cupiditate, natus obcaecati error quaerat. Corporis ipsa maxime, soluta hic veniam unde ex rem illum ipsam!
49 |
50 |
More Blah Blah Detail
51 |
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Quasi maiores voluptates cum quis maxime blanditiis asperiores tempore totam ipsam dignissimos? Dolorem dolores illo dignissimos quasi facilis cupiditate, natus obcaecati error quaerat. Corporis ipsa maxime, soluta hic veniam unde ex rem illum ipsam!
52 |
Lorem ipsum dolor sit amet consectetur adipisicing elit. Illo reiciendis ut explicabo sint repudiandae eligendi culpa laboriosam exercitationem! Inventore tenetur doloremque quaerat illo aspernatur sunt aperiam, nam temporibus veritatis cum vel corporis repellendus eveniet optio mollitia ab voluptates consequatur perspiciatis quasi atque? Rerum architecto nobis dicta laudantium neque, accusantium sapiente.
Lots of my Alien friends have moved on from Earth-Vision Reality TV. I hear the same complaints all the time - its too repetitive, there aren’t enough abductions, our plants in high level governments are too obvious. Blah-blah-blah. You know what I say? They are just setting the stage for the next big chapter, and I can’t wait...
Flying around the galaxy is all well and good, but if you’ve ever found yourself stranded in the middle of an anti-matter cloud for a few millennia, you’ll start wishing you had cared better for your UFO. Here are my top tricks to keep yourself at light speed.
Lots of my Alien friends have moved on from Earth-Vision Reality TV. I hear the same complaints all the time - its too repetitive, there aren’t enough abductions, our plants in high level governments are too obvious. Blah-blah-blah. You know what I say? They are just setting the stage for the next big chapter, and I can’t wait...
Flying around the galaxy is all well and good, but if you’ve ever found yourself stranded in the middle of an anti-matter cloud for a few millennia, you’ll start wishing you had cared better for your UFO. Here are my top tricks to keep yourself at light speed.
Fill out the form below to place an order for an alien abduction by one of our fine UFOs.
13 |
Your contact information
14 |
Your name
15 |
Phone number
16 |
Email
17 |
18 |
About your abduction
19 |
Requested date
20 |
How many people would you like abducted?
21 |
What type of UFO do you prefer?
22 |
23 |
Classic oval UFO
24 |
Star Wars-style Imperial cruiser
25 |
Battlestar Galactica-style Viper
26 |
Borg-style cube
27 |
28 |
What type of abduction experience do you want?
29 |
30 |
Tour of the solar system
31 |
Alien dinner and discussion
32 |
Alien dance lessons
33 |
Whale watching
34 |
35 |
Special requests:
36 |
Add me to your email list
37 |
38 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/static/exercises/4-forms/begin/img/galaxy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/static/exercises/4-forms/begin/img/galaxy.jpg
--------------------------------------------------------------------------------
/static/exercises/4-forms/begin/img/image credit.rtf:
--------------------------------------------------------------------------------
1 | {\rtf1\ansi\ansicpg1252\cocoartf1561\cocoasubrtf600
2 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;}
3 | {\colortbl;\red255\green255\blue255;}
4 | {\*\expandedcolortbl;;}
5 | \margl1440\margr1440\vieww10800\viewh8400\viewkind0
6 | \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
7 |
8 | \f0\fs24 \cf0 https://images.nasa.gov/details-GSFC_20171208_Archive_e000056.html\
9 | \
10 | Photo caption: Galaxy cluster Abell 370 contains several hundred galaxies tied together by the mutual pull of gravity. Photographed in a combination of visible and near-infrared light, the brightest and largest galaxies are the yellow-white, massive, elliptical galaxies containing many hundreds of billions of stars each. Spiral galaxies have younger populations of stars and are bluish. Mysterious-looking arcs of blue light are distorted images of remote galaxies behind the cluster. The cluster acts as a huge lens in space that magnifies and stretches images of background galaxies like a funhouse mirror. Photo Credit: NASA, ESA, and J. Lotz and the HFF Team (STScI).}
--------------------------------------------------------------------------------
/static/exercises/4-forms/begin/js/forms.js:
--------------------------------------------------------------------------------
1 | var form = document.getElementsByTagName("form")[0];
2 | form.addEventListener("submit", function(e) {
3 | e.preventDefault();
4 | sendData();
5 | });
6 |
7 | // https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript
8 | function sendData() {
9 | var XHR = new XMLHttpRequest();
10 | var urlEncodedData = "";
11 | var urlEncodedDataPairs = [];
12 |
13 | urlEncodedDataPairs.push(
14 | encodeURIComponent("name") +
15 | "=" +
16 | encodeURIComponent(form.querySelector("[name='name']").value)
17 | );
18 | urlEncodedDataPairs.push(
19 | encodeURIComponent("send_to") +
20 | "=" +
21 | encodeURIComponent(form.querySelector("[name='send_to']").value)
22 | );
23 | urlEncodedDataPairs.push(
24 | encodeURIComponent("email") +
25 | "=" +
26 | encodeURIComponent(form.querySelector("[name='email']").value)
27 | );
28 | urlEncodedDataPairs.push(
29 | encodeURIComponent("phone") +
30 | "=" +
31 | encodeURIComponent(form.querySelector("[name='phone']").value)
32 | );
33 | urlEncodedDataPairs.push(
34 | encodeURIComponent("date") +
35 | "=" +
36 | encodeURIComponent(form.querySelector("[name='date']").value)
37 | );
38 | urlEncodedDataPairs.push(
39 | encodeURIComponent("qty") +
40 | "=" +
41 | encodeURIComponent(form.querySelector("[name='qty']").value)
42 | );
43 |
44 | // radio buttons
45 | let radio = document.getElementsByName("ufotype");
46 | for (var i = 0, length = radio.length; i < length; i++) {
47 | if (radio[i].checked) {
48 | urlEncodedDataPairs.push(
49 | encodeURIComponent("ufotype") + "=" + encodeURIComponent(radio[i].value)
50 | );
51 | }
52 | }
53 |
54 | // dropdown menu
55 | var dropdown = form.querySelector("[name='abtype']");
56 | urlEncodedDataPairs.push(
57 | encodeURIComponent("abtype") +
58 | "=" +
59 | encodeURIComponent(dropdown.options[dropdown.selectedIndex].text)
60 | );
61 | urlEncodedDataPairs.push(
62 | encodeURIComponent("comments") +
63 | "=" +
64 | encodeURIComponent(form.querySelector("[name='comments']").value)
65 | );
66 | urlEncodedDataPairs.push(
67 | encodeURIComponent("subscribe") +
68 | "=" +
69 | encodeURIComponent(form.querySelector("[name='subscribe']").checked)
70 | );
71 |
72 | // Combine the pairs into a single string and replace all %-encoded spaces to
73 | // the '+' character; matches the behaviour of browser form submissions.
74 | urlEncodedData = urlEncodedDataPairs.join("&").replace(/%20/g, "+");
75 |
76 | // Define what happens on successful data submission
77 | XHR.addEventListener("load", function(event) {
78 | if (XHR.readyState === XHR.DONE) {
79 | if (XHR.status === 200) {
80 | alert("Your order has been received! Check your email.");
81 | } else {
82 | alert("Oh oh! We have a problem! " + XHR.responseText + ".");
83 | }
84 | }
85 | });
86 |
87 | // Define what happens in case of error
88 | XHR.addEventListener("error", function(event) {
89 | // This is normally a timeout or connection error.
90 | alert("Oops! Something went wrong.");
91 | });
92 |
93 | // Set up our request
94 | XHR.open(form.getAttribute("method"), form.getAttribute("action"));
95 |
96 | // Add the required HTTP header for form data POST requests
97 | XHR.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
98 |
99 | // Finally, send our data.
100 | XHR.send(urlEncodedData);
101 | }
102 |
--------------------------------------------------------------------------------
/static/exercises/4-forms/end/css/forms-end.css:
--------------------------------------------------------------------------------
1 | html {
2 | box-sizing: border-box;
3 | }
4 | *, *:before, *:after {
5 | box-sizing: inherit;
6 | }
7 | body {
8 | font-family: Arial, Helvetica, sans-serif;
9 | background-image: url(../img/galaxy.jpg);
10 | margin: 0;
11 | padding: 0;
12 | }
13 | .wrapper {
14 | width: 80%;
15 | margin: 0 auto;
16 | padding: 1em;
17 | background-color: #EFB106;
18 | display: flex;
19 | flex-flow: row nowrap;
20 | }
21 | section {
22 | flex-basis: 57%;
23 | margin-right: 10%;
24 | }
25 | aside {
26 | flex-basis: 33%;
27 | }
28 | p, [for="abtype"] {
29 | margin-bottom: 0;
30 | margin-top: 2rem;
31 | }
32 | fieldset, #abtype {
33 | margin-bottom: 2rem;
34 | }
35 | fieldset {
36 | border: 1px solid black;
37 | border-radius: 10px;
38 | }
39 | legend {
40 | font-weight: bold;
41 | font-size: 1.3rem;
42 | margin-top: 1.5rem;
43 | margin-bottom: 1rem;
44 | display: block;
45 | }
46 | label {
47 | display: block;
48 | }
49 | input:not([type="radio"]):not([type="checkbox"]),
50 | textarea {
51 | display: block;
52 | margin-bottom: 2rem;
53 | width: 20rem;
54 | font-family: Arial, Helvetica, sans-serif;
55 | font-size: 1em;
56 | border-radius: 10px;
57 | padding: 0 1rem;
58 | }
59 | textarea {
60 | height: 10rem;
61 | padding: 1rem;
62 | }
63 | select {
64 | font-size: 1rem;
65 | }
66 | button {
67 | margin: 2rem 0;
68 | background-color: #BB342F;
69 | color: white;
70 | border: none;
71 | font-size: 1rem;
72 | padding: 0.5rem 1rem;
73 | border-radius: 10px;
74 | }
75 | button:hover {
76 | background-color: #9A2B27;
77 | }
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/static/exercises/4-forms/end/forms-end.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Alien Abduction Order Form
7 |
8 |
9 |
10 |
11 |
12 |
13 |
Alien Abduction Order Form
14 |
Fill out the form below to place an order for an alien abduction by one of our fine UFOs.
15 |
69 |
70 |
71 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/static/exercises/4-forms/end/img/galaxy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/static/exercises/4-forms/end/img/galaxy.jpg
--------------------------------------------------------------------------------
/static/exercises/4-forms/end/img/image credit.rtf:
--------------------------------------------------------------------------------
1 | {\rtf1\ansi\ansicpg1252\cocoartf1561\cocoasubrtf600
2 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;}
3 | {\colortbl;\red255\green255\blue255;}
4 | {\*\expandedcolortbl;;}
5 | \margl1440\margr1440\vieww10800\viewh8400\viewkind0
6 | \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
7 |
8 | \f0\fs24 \cf0 https://images.nasa.gov/details-GSFC_20171208_Archive_e000056.html\
9 | \
10 | Photo caption: Galaxy cluster Abell 370 contains several hundred galaxies tied together by the mutual pull of gravity. Photographed in a combination of visible and near-infrared light, the brightest and largest galaxies are the yellow-white, massive, elliptical galaxies containing many hundreds of billions of stars each. Spiral galaxies have younger populations of stars and are bluish. Mysterious-looking arcs of blue light are distorted images of remote galaxies behind the cluster. The cluster acts as a huge lens in space that magnifies and stretches images of background galaxies like a funhouse mirror. Photo Credit: NASA, ESA, and J. Lotz and the HFF Team (STScI).}
--------------------------------------------------------------------------------
/static/exercises/4-forms/end/js/forms.js:
--------------------------------------------------------------------------------
1 | var form = document.getElementsByTagName("form")[0];
2 | form.addEventListener("submit", function(e) {
3 | e.preventDefault();
4 | sendData();
5 | });
6 |
7 | // https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript
8 | function sendData() {
9 | var XHR = new XMLHttpRequest();
10 | var urlEncodedData = "";
11 | var urlEncodedDataPairs = [];
12 |
13 | urlEncodedDataPairs.push(
14 | encodeURIComponent("name") +
15 | "=" +
16 | encodeURIComponent(form.querySelector("[name='name']").value)
17 | );
18 | urlEncodedDataPairs.push(
19 | encodeURIComponent("send_to") +
20 | "=" +
21 | encodeURIComponent(form.querySelector("[name='send_to']").value)
22 | );
23 | urlEncodedDataPairs.push(
24 | encodeURIComponent("email") +
25 | "=" +
26 | encodeURIComponent(form.querySelector("[name='email']").value)
27 | );
28 | urlEncodedDataPairs.push(
29 | encodeURIComponent("phone") +
30 | "=" +
31 | encodeURIComponent(form.querySelector("[name='phone']").value)
32 | );
33 | urlEncodedDataPairs.push(
34 | encodeURIComponent("date") +
35 | "=" +
36 | encodeURIComponent(form.querySelector("[name='date']").value)
37 | );
38 | urlEncodedDataPairs.push(
39 | encodeURIComponent("qty") +
40 | "=" +
41 | encodeURIComponent(form.querySelector("[name='qty']").value)
42 | );
43 |
44 | // radio buttons
45 | let radio = document.getElementsByName("ufotype");
46 | for (var i = 0, length = radio.length; i < length; i++) {
47 | if (radio[i].checked) {
48 | urlEncodedDataPairs.push(
49 | encodeURIComponent("ufotype") + "=" + encodeURIComponent(radio[i].value)
50 | );
51 | }
52 | }
53 |
54 | // dropdown menu
55 | var dropdown = form.querySelector("[name='abtype']");
56 | urlEncodedDataPairs.push(
57 | encodeURIComponent("abtype") +
58 | "=" +
59 | encodeURIComponent(dropdown.options[dropdown.selectedIndex].text)
60 | );
61 | urlEncodedDataPairs.push(
62 | encodeURIComponent("comments") +
63 | "=" +
64 | encodeURIComponent(form.querySelector("[name='comments']").value)
65 | );
66 | urlEncodedDataPairs.push(
67 | encodeURIComponent("subscribe") +
68 | "=" +
69 | encodeURIComponent(form.querySelector("[name='subscribe']").checked)
70 | );
71 |
72 | // Combine the pairs into a single string and replace all %-encoded spaces to
73 | // the '+' character; matches the behaviour of browser form submissions.
74 | urlEncodedData = urlEncodedDataPairs.join("&").replace(/%20/g, "+");
75 |
76 | // Define what happens on successful data submission
77 | XHR.addEventListener("load", function(event) {
78 | if (XHR.readyState === XHR.DONE) {
79 | if (XHR.status === 200) {
80 | alert("Your order has been received! Check your email.");
81 | } else {
82 | alert("Oh oh! We have a problem! " + XHR.responseText + ".");
83 | }
84 | }
85 | });
86 |
87 | // Define what happens in case of error
88 | XHR.addEventListener("error", function(event) {
89 | // This is normally a timeout or connection error.
90 | alert("Oops! Something went wrong.");
91 | });
92 |
93 | // Set up our request
94 | XHR.open(form.getAttribute("method"), form.getAttribute("action"));
95 |
96 | // Add the required HTTP header for form data POST requests
97 | XHR.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
98 |
99 | // Finally, send our data.
100 | XHR.send(urlEncodedData);
101 | }
102 |
--------------------------------------------------------------------------------
/static/exercises/5-github.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/static/exercises/5-github.zip
--------------------------------------------------------------------------------
/static/exercises/5-github/begin/calculator.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Calculator
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/static/exercises/5-github/begin/css/calculator.css:
--------------------------------------------------------------------------------
1 | html {
2 | box-sizing: border-box;
3 | }
4 | *, *:before, *:after {
5 | box-sizing: inherit;
6 | }
7 | body {
8 | padding: 0;
9 | margin: 0;
10 | }
11 | .wrapper {
12 | width: 400px;
13 | }
14 |
--------------------------------------------------------------------------------
/static/exercises/5-github/calculator instructions.txt:
--------------------------------------------------------------------------------
1 | We will work on creating a calculator for next week's work with JavaScript.
2 |
3 | Our goal is to create a calculator that looks exactly like the image calculator-spec.png, located in your day 5 folder.
4 |
5 | A few things to know about this calculator:
6 |
7 | * To get the symbols for math, you will need to look up their HTML codes. One place to do that is here:
8 |
9 | https://www.toptal.com/designers/htmlarrows/math/
10 |
11 | https://www.toptal.com/designers/htmlarrows/arrows/
12 |
13 | * The calculator buttons should be clickable. Next week, you'll program them. But for right now, somehow we need to code clickable buttons.
14 |
15 | * Colors used in this design include:
16 |
17 | - black: #000000
18 | - white: #ffffff
19 | - light grey: #d8d9db
20 | - buttons on hover: #ebebeb
21 | - button active state: #bbbcbe
22 | - function buttons: #df974c
23 | - function buttons on hover: #dfb07e
24 | - function button active state: #dd8d37
25 |
26 | * The overall width of this calculator is 400px.
27 |
28 |
29 | Suggested approach:
30 | * Create a wrapper with a width of 400px to set up the calculator.
31 | * Determine how many rows and columns we need.
32 | * Identify elements that occupy more than one column.
33 | * Determine the HTML tags required to code rows and cells.
34 | * Code a single row of 4 elements to start with and see if you can get that working.
35 | * Now add the other rows of 4 elements.
36 | * Finally, add the rows where there are fewer than 4 elements. What do you need to adjust to get these to work?
37 | * Once your layout is mostly working, add the colors and make it pretty.
38 |
--------------------------------------------------------------------------------
/static/exercises/5-github/calculator-spec.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FrontendMasters/bootcamp/998ffbceac4002b11952dcfcd4aa9b9280e7f025/static/exercises/5-github/calculator-spec.png
--------------------------------------------------------------------------------
/static/exercises/5-github/end/calculator.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Calculator
6 |
7 |
8 |
9 |