diff --git a/1-html-css/basics/assignment-1.md b/1-html-css/basics/assignment-1.md new file mode 100644 index 00000000..856fd971 --- /dev/null +++ b/1-html-css/basics/assignment-1.md @@ -0,0 +1,49 @@ +# HTML Assignment #1 + +Make a web page about something you think is cool or interesting. It could be a historic site, cultural event, person, place, a book or movie, or even something from your own life. It can be as personal or impersonal as you like, but I would enjoy learning something about your home region. + +This is not a research project, feel free to copy and paste content from other websites such as wikipedia (but make sure to remove footnotes, etc.) + +So far we have learned limited styling options, so keep the design clean and simple with complementary colors. Remember that margins and padding, text size, and border placement are all important considerations for a visually pleasing design. + +Remember to check the appearance of your page at different widths to see the impact of element wrapping. + +### This is your webpage, it can look however you want it to. It **should not** have the same layout, content, or colors as the example page. Get creative! + +
+ +

Assignment #1 Example Page - Watch Video

+
+ + + +
+ +#### Content Requirements: + +- include a title and sub-header for the page +- include three or more images +- include one or more ordered or unordered lists +- include one or more links + +#### Style requirements: + +- set a background color for the page +- set a different background color for at least one area of the page +- change the color of some or all links +- make the images all the same height or same width (not both, as this may distort the aspect ratio) +- set some spacing between images +- give at least one element on the page a border +- use at least one class selector +- use at least one id selector + +#### Extra challenge (optional): + +- change the color on links when a user hovers over them +- remove the underline from links +- set a maximum width for one or more elements +- use a color palette generator such as coolors.co to find or generate a nice looking color palette (look up how to use hex codes as css color values) + +## To submit: + +Follow the instructions in the [Git Steps](../../git-steps.md) document. diff --git a/1-html-css/basics/css-basics.css b/1-html-css/basics/css-basics.css new file mode 100644 index 00000000..d52be198 --- /dev/null +++ b/1-html-css/basics/css-basics.css @@ -0,0 +1,53 @@ +/* this is a CSS comment */ + +/* + +selector { + property: value; + property: value; +} + +*/ + +/* The element selector applies to every instance of that element */ +body { + background-color: beige; + color: brown; +} + +h1 { + color: green; +} + +span { + color: teal; + font-weight: 700; + margin: 30px; +} + +img { + padding: 20px; + /* padding-left: 20px; + padding-top: 10px; */ + margin: 10px; + border: 10px dashed darkcyan; + width: 400px !important; +} + +/* class selector, applies to any element with this class */ + +.orange-text { + color: orange; +} + +.gray-background { + background-color: gray; +} + +/* id selector, applies only to the single element with this id */ + +#block-wrapper { + background-color: bisque; + margin: 15px; + padding: 15px; +} diff --git a/1-html-css/basics/html-basic-tags.html b/1-html-css/basics/html-basic-tags.html new file mode 100644 index 00000000..1e81b867 --- /dev/null +++ b/1-html-css/basics/html-basic-tags.html @@ -0,0 +1,71 @@ + + + + + + HTML basic elements + + + + + + + + + + + +

heading one

+

heading two

+
heading six
+ +

paragraph

+ +
division
+ spananother spana third span +
pre-formatted
+ + + + MDN Web Docs HTML Element Reference + + + + this is going to be us! + + Kołobrzeg Lighthouse on the Polish Baltic coast + + +
+ + +
    +
  1. thing 3
  2. +
  3. thing 1
  4. +
  5. thing 2
  6. +
+ + + + +
+

This header is inside a div!

+

+ A paragraph usually won't have block elements inside it but + might have inline elements such as span or + anchor tags +

+
+ + diff --git a/1-html-css/blog-project.md b/1-html-css/blog-project.md new file mode 100644 index 00000000..4e0b05ba --- /dev/null +++ b/1-html-css/blog-project.md @@ -0,0 +1,50 @@ +# HTML & CSS Final Project + +Over the course of this program you will develop your own blogging web app. Eventually a user will be able to log into the app, create a profile, make posts, and see other people's profiles and posts. It is up to you whether this app will have a theme (such as a recipe sharing site, etc) or focus on particular kinds of content. However, do not plan for special features outside of the ability to create and edit a profile, and create and edit a blog post with or without photos. + +The first phase of this will be to build the HTML prototype. You will not be beholden to this prototype, you may decide to make changes to it over time. This is just a starting place to build from. + +Please keep your first draft of this very simple! This is not the time to play with animations or fancy visual tricks, because it is hard to predict how those things will work with the interactivity we will build in the future. Stick to a clean design with a simple layout and visually pleasing colors. + +Also, don't spend too much time coming up with content for the blog posts. Feel free to use lorem ipsum, copy wikipedia articles, song lyrics, knock knock jokes, or anything else you want to use as content. It doesn't have to be in English! + +### Project setup + +Create a new directory inside your code folder. Place all the files related to this project, including any images you may use, inside it. + +You will make two web pages, so each page will be a separate html file. I suggest styling them both with the same CSS file. If you like, you may additionally add separate CSS files for each page, so you may need up to three total CSS files. + +### Requirements + +#### Both pages + +Both pages must have + +- mobile-first responsive designs with at least mobile and desktop versions +- layouts using grid and/or flexbox +- a matching color scheme (I recommend taking the time to use a color palette generator to come up with something nice) +- use at least one custom font (from Google Fonts or any other source) + +#### Home page + +This will be the landing page for the site. Assume the user is logged in. + +The page should include at least navigation to the user profile, and several recent blog posts from different users. Each blog post should have: + +- a timestamp +- a username +- text (either the full post or the first line, etc) + +#### User Profile page + +This page will have some kind of bio. You decide what information is stored in the bio, it may be just one line, or responses to several questions/prompts, or a long bio, or anything else. It must also include a profile photo! + +In addition to the bio, include several of the user's most recent posts. (I won't notice or care whether these match the ones from the home page, the content is just a placeholder!) + +### Extra challenges (optional) + +- make some of the posts have images in them +- give each post a small user icon (such as a photo thumbnail) that is different for each user +- give the current user's posts an edit icon + - not all of the posts should be from the same user, so decide who the currently logged in user is +- include a tablet version as well as the mobile and desktop versions diff --git a/1-html-css/colors-and-sizes/index.html b/1-html-css/colors-and-sizes/index.html new file mode 100644 index 00000000..7ccfd1d9 --- /dev/null +++ b/1-html-css/colors-and-sizes/index.html @@ -0,0 +1,24 @@ + + + + + + + Colors and Sizes + + +
+ +
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
+
5
+
6
+ + diff --git a/1-html-css/colors-and-sizes/style.css b/1-html-css/colors-and-sizes/style.css new file mode 100644 index 00000000..51c908c9 --- /dev/null +++ b/1-html-css/colors-and-sizes/style.css @@ -0,0 +1,60 @@ +/* em is a measurement based on the size of an em dash + - en dash – em dash */ + +/* em is relative to the font size of the given container + rem, for "root em" is relative to the page's default font size + (or the "root font size") + therefore em is more flexible, but also easier to screw up! */ + +/* +vh - 1% of the viewport height +vw - 1% of the viewport width +% - a percentage of the parent's value +px - one pixel, use sparingly! +*/ + +body { + /* the page's default margin makes our 100vw and 100vh spill over the page */ + margin: 0; + background-color: #dfdfdf; +} + +.wrapper { + display: flex; + flex-wrap: wrap; + font-size: 2em; + color: #e87f3e; + background-color: rgb(98, 114, 100); + height: 50vh; + width: 70vw; + background-image: url(https://upload.wikimedia.org/wikipedia/commons/b/b0/Rottenburg_a.N._-_Wurmlingen_-_Kapellenberg_-_Ansicht_von_OSO_im_April_mit_Gegenlicht.jpg); + background-size: 70vw; +} + +.box { + /* flex properties */ + display: flex; + justify-content: center; + align-items: center; + + /* style properties */ + border: 1rem solid #1d263b8a; + /* The two extra digits are for the "alpha channel" + which controls opacity */ + height: 4rem; + width: 6rem; +} + +#one { + font-size: 3rem; + width: 50%; +} + +#six { + height: 3em; +} + +#eight { + /* don't do this! it works but it's weird! */ + height: 30vw; +} diff --git a/1-html-css/combining-grid-and-flexbox/index.html b/1-html-css/combining-grid-and-flexbox/index.html new file mode 100644 index 00000000..bd3e0856 --- /dev/null +++ b/1-html-css/combining-grid-and-flexbox/index.html @@ -0,0 +1,107 @@ + + + + + + Combining Flexbox and Grid + + + +
+ + +
+

+ If the automobile had followed the same development cycle as + the computer, a Rolls-Royce would today cost $100, get a + million miles per gallon, and explode once a year, killing + everyone inside. (Robert X. Cringely) For a long time it + puzzled me how something so expensive, so leading edge, + could be so useless. And then it occurred to me that a + computer is a stupid machine with the ability to do + incredibly smart things, while computer programmers are + smart people with the ability to do incredibly stupid + things. They are, in short, a perfect match. (Bill Bryson) + Java is, in many ways, C++-. (Michael Feldman) +

+

+ They have computers, and they may have other weapons of mass + destruction. (Janet Reno) The cheapest, fastest, and most + reliable components are those that aren't there. (Gordon + Bell) Everything that can be invented has been invented. + (Charles H. Duell, Commissioner, U.S. Office of Patents, + 1899) First, solve the problem. Then, write the code. (John + Johnson) +

+

+ I've finally learned what 'upward compatible' means. It + means we get to keep all our old mistakes. (Dennie van + Tassel) It is not about bits, bytes and protocols, but + profits, losses and margins. (Lou Gerstner) The best thing + about a boolean is even if you are wrong, you are only off + by a bit. (Anonymous) +

+

+ I think there's a world market for about 5 computers. + (Thomas J. Watson, Chairman of the Board, IBM, circa 1948) + The trouble with programmers is that you can never tell what + a programmer is doing until it's too late. (Seymour Cray) + Complexity kills. It sucks the life out of developers, it + makes products difficult to plan, build and test, it + introduces security challenges, and it causes end-user and + administrator frustration. (Ray Ozzie) The only people who + have anything to fear from free software are those whose + products are worth even less. (David Emery) +

+

+ If McDonalds were run like a software company, one out of + every hundred Big Macs would give you food poisoning, and + the response would be, 'We're sorry, here's a coupon for two + more.' (Mark Minasi) It has been said that the great + scientific disciplines are examples of giants standing on + the shoulders of other giants. It has also been said that + the software industry is an example of midgets standing on + the toes of other midgets. (Alan Cooper) There are two ways + of constructing a software design. One way is to make it so + simple that there are obviously no deficiencies. And the + other way is to make it so complicated that there are no + obvious deficiencies. (C.A.R. Hoare) +

+
+ + +
+ + diff --git a/1-html-css/combining-grid-and-flexbox/style.css b/1-html-css/combining-grid-and-flexbox/style.css new file mode 100644 index 00000000..6ed9f94f --- /dev/null +++ b/1-html-css/combining-grid-and-flexbox/style.css @@ -0,0 +1,98 @@ +body { + margin: 0; + background-color: #ebf2fa; + font-size: 1.2em; + color: #381d2a; +} + +#wrapper { + display: grid; + grid-template-columns: min-content 1fr min-content; + grid-template-rows: min-content 1fr min-content min-content; + grid-template-areas: + "header header header" + "contents main ." + "contents main tips" + "footer footer footer"; + min-height: 100vh; + gap: 1rem; +} + +#header { + grid-area: header; + background-color: #05668d; + padding: 0.5rem; + color: #ebf2fa; + + display: flex; + justify-content: space-between; + align-items: center; +} + +#title { + font-size: 2rem; + font-weight: 600; +} + +#contents { + grid-area: contents; + margin-left: 1rem; + padding: 0.5rem; + background-color: #66a182; + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +#main { + grid-area: main; +} + +.topic { + white-space: nowrap; + padding: 0 0.5em; +} + +#contents > h4 { + text-decoration: underline; + padding: 0.5em 0; +} + +#tips { + grid-area: tips; + height: fit-content; +} + +#footer { + grid-area: footer; + background-color: #427aa1; + display: flex; + justify-content: space-evenly; +} + +a { + color: #05668d; + text-decoration: none; + font-weight: 600; +} + +.navigation a { + color: #ebf2fa; + margin: 0.5rem; +} + +a:hover { + color: #f7a072; +} + +#tips { + background-color: #f4f8fc; + padding: 1rem; + border: 3px solid #66a182; + margin-right: 1rem; + min-width: 7em; +} + +h4 { + margin: 0; +} diff --git a/1-html-css/flexbox/flexbox-assignment/css-assignment-1.md b/1-html-css/flexbox/flexbox-assignment/css-assignment-1.md new file mode 100644 index 00000000..f57383e9 --- /dev/null +++ b/1-html-css/flexbox/flexbox-assignment/css-assignment-1.md @@ -0,0 +1,15 @@ +# CSS Assignment #1: Flexbox + +#### Project setup + +Start by copying (not moving!) the files from this folder, [index.html](index.html) and [style.css](style.css), into an assignment folder inside your code folder. Open the HTML file with your Live Server, and then start editing the CSS to meet the requirements you see on the page. + +#### Requirements: + +Follow the instructions on the page, and align the items as described using _only_ flexbox properties. You will need to use both `flex container` and `flex item` properties. + +#### Tips: + +- The page will refresh every time you save. To prevent having to scroll on each save, you can "comment out" the sections at the top of the HTML as you finish them. Remember to remove the comments before you turn it in! +- Reference the [CSS Tricks Guide to Flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) to help you +- When you are ready to submit, remember to make a pull request following the steps in our [Git Steps](../../../git-steps.md) document. diff --git a/1-html-css/flexbox/flexbox-assignment/index.html b/1-html-css/flexbox/flexbox-assignment/index.html new file mode 100644 index 00000000..be17e49e --- /dev/null +++ b/1-html-css/flexbox/flexbox-assignment/index.html @@ -0,0 +1,95 @@ + + + + + + Flexbox Challenge + + + + +

CSS Flexbox

+ +

Challenge 1

+

Horizontally list these bubbles using Flexbox

+
+
+
+
+
+ +

Challenge 2

+

+ Horizontally align these bubbles to the right and backwards (green, + red, blue) +

+
+
+
+
+
+ +

Challenge 3

+

+ Horizontally align these bubbles to the right and NOT backwards + (blue, red, green) +

+
+
+
+
+
+ +

Challenge 4

+

Horizontally align these bubbles and space them out evenly

+
+
+
+
+
+ +

Challenge 5

+

+ Horizontally align these bubbles, center them together (not spaced), + and add a 20px gap +

+
+
+
+
+
+ +

Challenge 6

+

+ Center the text inside each bubble. (Align the text both vertically + and horizontally) +

+
+
Blue
+
Red
+
Green
+
+ +

Challenge 7

+

+ Horizontally align these bubbles, and let the red one stretch out to + fill the screen +

+
+
+
+
+
+ +

Challenge 8

+

+ Vertically align these bubbles, center them, and move the red bubble + to the bottom +

+
+
+
+
+
+ + diff --git a/1-html-css/flexbox/flexbox-assignment/style.css b/1-html-css/flexbox/flexbox-assignment/style.css new file mode 100644 index 00000000..57d6cd76 --- /dev/null +++ b/1-html-css/flexbox/flexbox-assignment/style.css @@ -0,0 +1,66 @@ +.challenge-1 { + /* write code here */ +} + +.challenge-2 { + /* write code here */ +} + +.challenge-3 { + /* write code here */ +} + +.challenge-4 { + /* write code here */ +} + +.challenge-5 { + /* write code here */ +} + +/* +Tip: This is called the "child selector". +It selects all .bubble elements that are direct +children of .challenge-6 elements. +*/ +.challenge-6 .bubble { + /* write code here */ +} + +.challenge-7 { + display: flex; +} + +.challenge-7 .red { + /* write code here */ +} + +.challenge-8 { + /* write code here */ +} + +.challenge-8 .red { + /* write code here */ +} + +/* DO NOT CHANGE ANYTHING BELOW HERE */ + +.bubble { + height: 5em; + width: 5em; + color: white; + border-radius: 50%; + border: 0.1em solid black; +} + +.red { + background-color: red; +} + +.blue { + background-color: blue; +} + +.green { + background-color: green; +} diff --git a/1-html-css/flexbox/index.html b/1-html-css/flexbox/index.html new file mode 100644 index 00000000..ac4e0418 --- /dev/null +++ b/1-html-css/flexbox/index.html @@ -0,0 +1,27 @@ + + + + + + Flexbox Lesson + + + +
+
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
+
+
1
+
2
+
+
+ + diff --git a/1-html-css/flexbox/style.css b/1-html-css/flexbox/style.css new file mode 100644 index 00000000..7d0ed40b --- /dev/null +++ b/1-html-css/flexbox/style.css @@ -0,0 +1,64 @@ +#wrapper { + display: flex; + flex-wrap: wrap; +} + +.flex-parent { + /* style properties */ + background-color: lightblue; + height: 40vh; + border: 10px solid navy; + + /* flexbox properties */ + display: flex; + flex-direction: row; + flex-wrap: wrap; + + /* justify-content: space-evenly; */ + align-items: center; + /* align-content: space-between; */ + + /* row-gap: 1em; */ + /* column-gap: 1em; */ + gap: 1em 3em; +} + +.box { + /* style properties */ + height: 100px; + width: 100px; + background-color: orchid; + border: 2px solid navy; + border-radius: 10%; + font-size: 3em; + color: white; + + /* flex properties */ + display: flex; + align-items: center; + justify-content: center; +} + +#one { + font-size: 1em; + flex-shrink: 3; + align-self: flex-end; +} + +#two { + order: 3; + flex-grow: 2; +} + +#four { + order: 1; + flex-grow: 2; +} + +#six { + order: -1; +} + +#eight { + align-self: flex-start; +} diff --git a/1-html-css/grid/columns-and-rows.css b/1-html-css/grid/columns-and-rows.css new file mode 100644 index 00000000..6775dc47 --- /dev/null +++ b/1-html-css/grid/columns-and-rows.css @@ -0,0 +1,58 @@ +.grid-container { + display: grid; + grid-template-columns: 10rem 1fr 10rem; + grid-template-rows: 8vh 40vh 1fr 10vh min-content; +} + +.box { + font-size: 3em; + padding: 0.5rem; + font-weight: 700; + text-shadow: 2px 2px 10px #fff; +} + +#one { + grid-column-start: 1; + grid-column-end: 4; + + background-color: red; +} + +#two { + grid-row-start: 2; + grid-row-end: 5; + background-color: blue; +} + +#three { + grid-column: 3 / 4; + background-color: green; +} + +.main { + grid-row: 2/5; + display: flex; + flex-direction: column; + gap: 2em; +} + +#four { + height: 50vh; + background-color: yellow; +} + +#five { + height: 30vh; + background-color: purple; +} + +#six { + grid-column: 3/4; + grid-row: 4/5; + background-color: orange; +} + +#seven { + grid-column: 1 / 4; + background-color: hotpink; +} diff --git a/1-html-css/grid/grid-areas.css b/1-html-css/grid/grid-areas.css new file mode 100644 index 00000000..c9df4f23 --- /dev/null +++ b/1-html-css/grid/grid-areas.css @@ -0,0 +1,63 @@ +.grid-container { + display: grid; + grid-template-columns: 10rem 1fr 10rem; + grid-template-rows: 8vh 40vh 1fr 10vh min-content; + grid-template-areas: + "header header header" + "sidebar-left main sidebar-right" + "sidebar-left main . " + "sidebar-left main note" + "footer footer footer"; +} + +.box { + font-size: 3em; + padding: 0.5rem; + font-weight: 700; + text-shadow: 2px 2px 10px #fff; + display: flex; + justify-content: center; + align-items: center; +} + +#one { + grid-area: header; + background-color: red; +} + +#two { + grid-area: sidebar-left; + background-color: blue; +} + +#three { + grid-area: sidebar-right; + background-color: green; +} + +.main { + grid-area: main; + display: flex; + flex-direction: column; + gap: 2em; +} + +#four { + height: 50vh; + background-color: yellow; +} + +#five { + height: 30vh; + background-color: purple; +} + +#six { + grid-area: note; + background-color: orange; +} + +#seven { + grid-area: footer; + background-color: hotpink; +} diff --git a/1-html-css/grid/grid-assignment/css-assignment-2.md b/1-html-css/grid/grid-assignment/css-assignment-2.md new file mode 100644 index 00000000..1c983140 --- /dev/null +++ b/1-html-css/grid/grid-assignment/css-assignment-2.md @@ -0,0 +1,21 @@ +# CSS Assignment #2: Grid + +#### Project setup + +Start by copying (not moving!) the files from this folder, [index.html](index.html) and [style.css](style.css), into an assignment folder inside your code folder. Open the HTML file with your Live Server, and then start editing the CSS to meet the requirements described here. + +#### Requirements: + +You goal is to make the page look like this: + +![CSS Grid layout with header and footer, and left and right sidebars](./grid-solution.gif) + +You must use CSS Grid properties. The left column should be a fixed size, and right sidebar should be a dynamic size. + +There is no need to make any changes to the html. + +#### Tips: + +- You can use column and row definitions, or grid areas. Either way works just as well. +- Reference the [CSS Tricks Guide to CSS Grid](https://css-tricks.com/snippets/css/complete-guide-grid/) to help you +- When you are ready to submit, remember to make a pull request following the steps in our [Git Steps](../../../git-steps.md) document. diff --git a/1-html-css/grid/grid-assignment/grid-solution.gif b/1-html-css/grid/grid-assignment/grid-solution.gif new file mode 100644 index 00000000..2e8eae83 Binary files /dev/null and b/1-html-css/grid/grid-assignment/grid-solution.gif differ diff --git a/1-html-css/grid/grid-assignment/index.html b/1-html-css/grid/grid-assignment/index.html new file mode 100644 index 00000000..209df0cd --- /dev/null +++ b/1-html-css/grid/grid-assignment/index.html @@ -0,0 +1,19 @@ + + + + + + CSS Grid Challenge + + + + +
+ + +
Main contents/body of the page
+ + +
+ + diff --git a/1-html-css/grid/grid-assignment/style.css b/1-html-css/grid/grid-assignment/style.css new file mode 100644 index 00000000..02461a4b --- /dev/null +++ b/1-html-css/grid/grid-assignment/style.css @@ -0,0 +1,18 @@ +#wrapper { + font-size: 2em; + gap: 1rem; + /* Add new properties here */ +} + +/* Add new selectors and new CSS here */ + +/* DO NOT CHANGE ANYTHING BELOW THIS LINE */ +#wrapper > * { + background-color: #ddd; + min-height: 15vh; + padding: 0.5em; +} + +article { + height: 85vh; +} diff --git a/1-html-css/grid/index.html b/1-html-css/grid/index.html new file mode 100644 index 00000000..8e3e509c --- /dev/null +++ b/1-html-css/grid/index.html @@ -0,0 +1,22 @@ + + + + + + Grid + + + +
+
1
+
2
+
3
+
+
4
+
5
+
+
6
+
7
+
+ + diff --git a/1-html-css/media-queries/index.html b/1-html-css/media-queries/index.html new file mode 100644 index 00000000..75740f97 --- /dev/null +++ b/1-html-css/media-queries/index.html @@ -0,0 +1,108 @@ + + + + + + Responsive Design & Media Queries + + + + +
+ + +
+

+ If the automobile had followed the same development cycle as + the computer, a Rolls-Royce would today cost $100, get a + million miles per gallon, and explode once a year, killing + everyone inside. (Robert X. Cringely) For a long time it + puzzled me how something so expensive, so leading edge, + could be so useless. And then it occurred to me that a + computer is a stupid machine with the ability to do + incredibly smart things, while computer programmers are + smart people with the ability to do incredibly stupid + things. They are, in short, a perfect match. (Bill Bryson) + Java is, in many ways, C++-. (Michael Feldman) +

+

+ They have computers, and they may have other weapons of mass + destruction. (Janet Reno) The cheapest, fastest, and most + reliable components are those that aren't there. (Gordon + Bell) Everything that can be invented has been invented. + (Charles H. Duell, Commissioner, U.S. Office of Patents, + 1899) First, solve the problem. Then, write the code. (John + Johnson) +

+

+ I've finally learned what 'upward compatible' means. It + means we get to keep all our old mistakes. (Dennie van + Tassel) It is not about bits, bytes and protocols, but + profits, losses and margins. (Lou Gerstner) The best thing + about a boolean is even if you are wrong, you are only off + by a bit. (Anonymous) +

+

+ I think there's a world market for about 5 computers. + (Thomas J. Watson, Chairman of the Board, IBM, circa 1948) + The trouble with programmers is that you can never tell what + a programmer is doing until it's too late. (Seymour Cray) + Complexity kills. It sucks the life out of developers, it + makes products difficult to plan, build and test, it + introduces security challenges, and it causes end-user and + administrator frustration. (Ray Ozzie) The only people who + have anything to fear from free software are those whose + products are worth even less. (David Emery) +

+

+ If McDonalds were run like a software company, one out of + every hundred Big Macs would give you food poisoning, and + the response would be, 'We're sorry, here's a coupon for two + more.' (Mark Minasi) It has been said that the great + scientific disciplines are examples of giants standing on + the shoulders of other giants. It has also been said that + the software industry is an example of midgets standing on + the toes of other midgets. (Alan Cooper) There are two ways + of constructing a software design. One way is to make it so + simple that there are obviously no deficiencies. And the + other way is to make it so complicated that there are no + obvious deficiencies. (C.A.R. Hoare) +

+
+ + +
+ + diff --git a/1-html-css/media-queries/responsive-assignment/css-assignment-3.md b/1-html-css/media-queries/responsive-assignment/css-assignment-3.md new file mode 100644 index 00000000..f69910fb --- /dev/null +++ b/1-html-css/media-queries/responsive-assignment/css-assignment-3.md @@ -0,0 +1,35 @@ +# CSS Assignment #3: Responsive Design + +#### Project setup + +Start by copying (not moving!) the files from this folder, [index.html](index.html), [style.css](style.css), and ocean.jpg into an assignment folder inside your code folder. Open the HTML file with your Live Server, and then start editing the CSS to meet the requirements described here. + +CSS has been provided for a mobile version of the site. Reduce your browser size or use the "responsive viewport mode" in your browser's devtools to see what it will look like in a width smaller than 500px. + +### Requirements: + +You will add three media queries to add three new responsive layouts. The regular, mobile version of the site doesn't use either flexbox or grid to create the layout. It only uses flexbox for centering the header. + +### 500px + +At `min-width: 500px` use flexbox to make the layout look like this: + +![layout with text on alternating sides of the image](./solutions/responsive-500.gif) + +### 750px + +At `min-width: 750px` add more flexbox properties to make the layout look like this: + +![layout with tiled cards containing images and text](./solutions/responsive-750.gif) + +### 1000px + +At `min-width: 1000px` use CSS grid to make the layout look like this: + +![layout with profile on the left and gallery on the right](./solutions/responsive-1000.gif) + +#### Tips: + +- Start by thoroughly reading the HTML to make sure you understand how the elements on the page are organized +- Remember that only **direct children** of flex/grid containers are flex/grid items that are subject to the flex/grid rules. +- When you are ready to submit, remember to make a pull request following the steps in our [Git Steps](../../../git-steps.md) document. diff --git a/1-html-css/media-queries/responsive-assignment/index.html b/1-html-css/media-queries/responsive-assignment/index.html new file mode 100644 index 00000000..4d99b18e --- /dev/null +++ b/1-html-css/media-queries/responsive-assignment/index.html @@ -0,0 +1,111 @@ + + + + + + CSS Grid Challenge + + + + +
Photo Gallery
+
+
+ Photographer Profile + photographer capturing a sunset +

+ Lorem ipsum dolor sit amet consectetur, adipisicing elit. + Aliquam cumque autem magni quas modi! Voluptatibus earum + iste nam sint unde odio, voluptates et tempora ab + praesentium nihil eum porro excepturi. +

+
+ + +
+ + diff --git a/1-html-css/media-queries/responsive-assignment/ocean.jpg b/1-html-css/media-queries/responsive-assignment/ocean.jpg new file mode 100644 index 00000000..c35d0a62 Binary files /dev/null and b/1-html-css/media-queries/responsive-assignment/ocean.jpg differ diff --git a/1-html-css/media-queries/responsive-assignment/solutions/responsive-1000.gif b/1-html-css/media-queries/responsive-assignment/solutions/responsive-1000.gif new file mode 100644 index 00000000..07eaea78 Binary files /dev/null and b/1-html-css/media-queries/responsive-assignment/solutions/responsive-1000.gif differ diff --git a/1-html-css/media-queries/responsive-assignment/solutions/responsive-500.gif b/1-html-css/media-queries/responsive-assignment/solutions/responsive-500.gif new file mode 100644 index 00000000..d16eca8d Binary files /dev/null and b/1-html-css/media-queries/responsive-assignment/solutions/responsive-500.gif differ diff --git a/1-html-css/media-queries/responsive-assignment/solutions/responsive-750.gif b/1-html-css/media-queries/responsive-assignment/solutions/responsive-750.gif new file mode 100644 index 00000000..f6ced3bb Binary files /dev/null and b/1-html-css/media-queries/responsive-assignment/solutions/responsive-750.gif differ diff --git a/1-html-css/media-queries/responsive-assignment/style.css b/1-html-css/media-queries/responsive-assignment/style.css new file mode 100644 index 00000000..9ed7ae1b --- /dev/null +++ b/1-html-css/media-queries/responsive-assignment/style.css @@ -0,0 +1,36 @@ +body { + margin: 0; +} + +#profile { + background-color: #f9b8b6; + padding: 1em; + margin: 1em; +} + +#profile > img { + outline: 0.3rem solid #fff; + margin: 0.5em 0; +} + +#profile > span { + font-size: 1.3em; + font-weight: 600; + padding-bottom: 1em; +} + +.card { + border: 3px solid #006d9e; + margin: 0.2rem; +} + +img { + width: 100%; +} + +header { + background-color: #a7cddf; + font-size: 2em; + display: flex; + justify-content: center; +} diff --git a/1-html-css/media-queries/style.css b/1-html-css/media-queries/style.css new file mode 100644 index 00000000..e4ce16df --- /dev/null +++ b/1-html-css/media-queries/style.css @@ -0,0 +1,82 @@ +/* This page uses the same styles from the Combining CSS Grid & Flexbox lesson */ +/* Plus ... */ + +/* tablet layout */ +@media screen and (max-width: 1024px) { + #wrapper { + grid-template-columns: min-content 1fr; + grid-template-areas: + "header header" + "contents main" + "contents tips" + "footer footer"; + gap: 0.5rem; + } + + #contents { + margin-left: 0.5rem; + } + + #main { + margin-right: 0.5rem; + } + + #tips { + margin-right: 0.5rem; + } +} + +/* phone layout */ +@media screen and (max-width: 500px) { + #wrapper { + grid-template-columns: unset; + grid-template-areas: + "header" + "contents" + "main" + "tips" + "footer"; + gap: 0; + } + + #header { + flex-direction: column; + } + + #contents { + margin: 0; + flex-direction: row; + font-size: 0.8em; + justify-content: space-evenly; + } + + #contents > h4 { + display: none; + } + + .topic { + padding: 0; + } + + #main { + padding: 0 1rem; + } + + #tips { + margin: 0.5rem; + } + + #footer { + flex-direction: column; + align-items: flex-end; + padding: 0.5rem; + } + + #footer > a { + margin: 0.2rem; + } + + a { + font-weight: 100; + } +} diff --git a/2-javascript/assignments/js-assignment-1.md b/2-javascript/assignments/js-assignment-1.md new file mode 100644 index 00000000..c14c5266 --- /dev/null +++ b/2-javascript/assignments/js-assignment-1.md @@ -0,0 +1,42 @@ +# JavaScript Assignment #1: Strings and Numbers + +In this assignment you will perform some basic operations and `console.log()` the results. + +Create a new file inside your code folder for this assignment. You will run your code using `node .js`. Remember that the path to your file is always relative to your working directory! + +You may do these challenges all together in one file, or in separate files, according to your preference. You will turn them in all together. + +### Strings + +- Create a constant variable and assign it a _string literal_ with your name +- Console log the _length_ of the string +- Console log the _string template_ "Hello, my name is \_\_\_\_" but fill in the blank with the name variable. +- Console log the _string template_ "When my friends see me they shout \_\_\_\_!" but fill in the blank with your name in all caps. (Use a string method to capitalize it!) + +### Numbers + +#### Challenge 1: + +- Create a constant variable with a number in it. (You can choose any number, with any number of digits.) +- Multiply the number by 2 +- Add 8 +- Divide by 2 +- Subtract the original number +- Console log the result +- The result should be 4 + +Tips: + +- You can use any number of variables to do this, but you only need one or two! +- If you choose to combine operations within a single line, don't forget about mathematical order of operations + +#### Challenge 2: + +- Find the area of a circle with a given radius (), rounded to four digits +- Console log the result + +Tips: + +- A radius of 2 should give you 12.5664, and a radius of 3 should give you 28.2743 +- Don't forget about order of operations! +- When you are ready to submit, make a pull request following the steps in our [Git Steps](../../../git-steps.md) document. diff --git a/2-javascript/assignments/js-assignment-2.md b/2-javascript/assignments/js-assignment-2.md new file mode 100644 index 00000000..4eea6d0c --- /dev/null +++ b/2-javascript/assignments/js-assignment-2.md @@ -0,0 +1,39 @@ +# JavaScript Assignment #2: Booleans + +You may do these challenges all together in one file, or in separate files, according to your preference. You will turn them in all together. + +## Challenge #1 + +- Create a constant variable called `personAge` and assign it a number between 1 and 100 +- Create a constant variable called `isAdult` and assign it a _boolean expression_ determining whether that number is above or below 18 +- Create a constant variable called `isElderly` and assign it a _boolean expression_ determining whether that number is above or below 60 +- Create a template string that will read like this: `Is this person an adult? true. Is this person elderly? false` (but fill in the correct variables for true and false) +- **TIP**: Make sure you test by changing the value of `personAge` to make sure it works for children, adults below 60, and adults over 60 + +#### Extra challenges (you may do either or neither or both!) + +- Make `personAge` a random number between 0 and 100. (You may want to log the number to make sure your booleans are evaluating correctly!) +- Use a conditional statement to log "This person is a child" or "This person is an adult" or "This person is elderly" to the console. + +## Challenge #2 + +The string function [.includes()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes) returns a boolean. It determines whether a string includes a given substring. + +```js +let sentence = "This is an example sentence" +let includesExample = sentence.includes("example") +console.log(includesExample) // true +``` + +For this challenge + +- create a constant variable called `lyric` and assign it your favorite song lyric. +- create a constant variable called `includesLove` and assign it a JS expression determining whether your lyric includes the word "love" +- do the same thing with the words "heart", "life", "baby", and "yeah". +- create and log a constant variable called `isTypical` and assign it a boolean expression determining whether ANY of the conditions are true +- create and log a constant variable called `isVeryTypical` and assign it a boolean expression determining whether ALL of the conditions are true + +#### Extra challenges (optional) + +- Use a conditional statement to log "This song is typical" or "This song is very typical" or "This song is not typical" to the console. +- Find (or write!) a song lyric that meets each condition. Repeat the previous step for each lyric. diff --git a/2-javascript/assignments/js-assignment-3.md b/2-javascript/assignments/js-assignment-3.md new file mode 100644 index 00000000..48f16a5a --- /dev/null +++ b/2-javascript/assignments/js-assignment-3.md @@ -0,0 +1,21 @@ +# JavaScript Assignment #3: Conditionals + +You may do these challenges all together in one file, or in separate files, according to your preference. You will turn them in all together. + +## Challenge #1 + +- Create a constant variable called `movieTitle` and assign it a string with the title of a movie you like +- Create a constant variable called `isScary` and assign it either `true` or `false` +- Create a constant variable called `isRomantic` and assign it either `true` or `false` +- Write a conditional statement that will log _only one_ of these sentences to the console: + - this movie is both romantic and scary! + - this movie is romantic + - this movie is scary + - this movie is neither romantic nor scary +- In each outcome, replace "this movie" with the title of your movie. +- TIP: try out assigning the boolean variable to different values of `true` and `false` to make sure all of the conditions work correctly + +#### Extra challenge (optional) + +- Add another variable `isFunny` and see if you can represent all possible combinations +- Note that this adds a significant number of new options! Can you figure out how to solve it with nested conditionals? (Putting conditional statements inside of other conditionals?) diff --git a/2-javascript/assignments/js-assignment-4.md b/2-javascript/assignments/js-assignment-4.md new file mode 100644 index 00000000..ccc4f045 --- /dev/null +++ b/2-javascript/assignments/js-assignment-4.md @@ -0,0 +1,30 @@ +# JavaScript Assignment #4: Loops + +You may do these challenges all together in one file, or in separate files, according to your preference. You will turn them in all together. + +## Challenge #1 + +- Paste this line into your code: + - `const wordList = ["every", "word", "in", "this", "array", "should", "be", "capitalized"]` +- Write a for..of loop that logs each word in the array +- Now, within the loop, capitalize each word + +#### Extra challenges (you may any or all or none of these) + +- (this is actually a strings challenge) Try capitalizing only the first letter. There is no string method that does this, so you will need to utilize `.slice()` +- Rather than simply logging each word in the array, try creating a new array and adding each capitalized word to it +- Add each capitalized word to a string instead of (or in addition to) an array + +## Challenge #2 + +- Write a loop that will execute exactly 10 times. You can do this with either a while loop or a "classic" for loop +- For each loop, console log whether the number is divisible by 3. (You can do this with modulo) + - you will need a conditional inside your loop for this! + - you can log "true" and "false", or if you prefer, "yes" and "no" + +#### Extra challenges (optional) + +- Solve FizzBuzz without looking up a solution! This is one of the classic beginning programming challenges +- [Here](https://en.wikipedia.org/wiki/Fizz_buzz) is an explanation of the children's math game FizzBuzz +- Write a JS loop that will go 40 times, and for each number console log the number, and either Fizz, Buzz, or FizzBuzz next to it +- Be mindful of the order of your conditions! diff --git a/2-javascript/assignments/js-assignment-5.md b/2-javascript/assignments/js-assignment-5.md new file mode 100644 index 00000000..28a6be0c --- /dev/null +++ b/2-javascript/assignments/js-assignment-5.md @@ -0,0 +1,38 @@ +# JavaScript Assignment #5: Functions + +You may do these challenges all together in one file, or in separate files, according to your preference. You will turn them in all together. + +## Challenge #1: Capitalize + +- Declare a function called `capitalize` that takes one argument, `word` +- Within the function, capitalize the word +- Return the capitalized word +- When you run `console.log(capitalize("hello"))` you should get `HELLO` + +## Challenge #2: Percentage Calculator + +- Declare a function called `percentCalc` that takes two arguments, `amount` and `percentage` +- Return the given percentage of the amount +- When you run `console.log(percentCalc(200, 20))` you should get `40` + +## Challenge #3: Divisible + +- Declare a function called `divisible` that takes two argments, `dividend` and `divisor` +- Determine whether the dividend is divisible by the divisor (meaning the division will result in a whole number with remainder) + - Tip: Use the modulo operator +- Return true or false +- When you run `console.log(divisble(6, 3))` you should get `true` +- When you run `console.log(divisble(15, 4))` you should get `false` + +## Challenge #4: Friend, Enemy + +- Declare a function called `greeting` that takes in two arguments, `firstName` and `status` +- Inside the function, write a conditional that determined whether `status` is the string `"friend"` or the string `"enemy"` +- If the person is a friend, return the string that welcomes them by their name +- If the person is an enemy, return a string that tells them to go away +- When you run `console.log(greeting("Superman", "friend"))` you should get something like `Hello Superman!` +- When you run `console.log(greeting("Lex Luthor", "enemy"))` you should get something like `Go away Lex Luthor!` + +#### Extra challenge (optional) + +- What do you think this function should do if the second argument doesn't match `"friend"` or `"enemy"`? Think of something fun and implement it! diff --git a/2-javascript/assignments/js-assignment-6.md b/2-javascript/assignments/js-assignment-6.md new file mode 100644 index 00000000..2e0929b3 --- /dev/null +++ b/2-javascript/assignments/js-assignment-6.md @@ -0,0 +1,73 @@ +# JavaScript Assignment #6: Objects + +You will complete all of these challenges in the same file. + +Start by pasting this object into your code: + +```javascript +const restaurant = { + name: "Gigi's Pizza Shack", + address: "123 Main St, Portland OR 97200", + tags: ["pizza", "family", "dine-in", "take-out", "arcade"], + website: "http://www.gigispizza.com/", + staff: { + owner: { + name: "Gigi", + "phone number": "123-234-3456", + }, + manager: { + name: "Rose", + "phone number": "234-345-4567", + }, + chef: { + name: "Musa", + "phone number": "345-456-5678", + }, + }, +} +``` + +## Challenge #1: Accessing Data + +- Use dot or bracket notation as needed to console log the following information: + - The restaurant's name + - The third item ("dine-in") from the list of tags + - The chef's name +- Use a loop to console log each of the tags + +## Challenge #2: Updating Data + +- Using dot or bracket notation to update the object + - Move the restaurant to somewhere in your city (change the address) + - Hire yourself to the staff (make up a position for yourself and add it to the "staff") + - make sure to add yourself as an object with your name and (fake!) phone number + - Remove the website from the object +- Console log the object to see the changes + +## Challenge #3: Creating a new object + +- Write a new object literal that represents a menu with prices. It can include whatever dishes you like. Give it at least four dishes. An example might look like this: + +```javascript +const menu = { + burger: 5.0, + fries: 3.5, +} +``` + +## Challenge #4: Creating an object method + +- Write an `order` method on the `menu` object that does the following: + - takes one argument, an array of strings + - loop over the strings, and add up the total for the corresponding menu items + - return the total cost of the order +- For example: + - `console.log(menu.order(["burger", "fries"])) // 8.5` + - `console.log(menu.order(["burger", "fries", "fries"])) // 12` + +#### Extra challenges (optional) + +- Use dot or bracket notation to add the menu to the restaurant object + - Make an order using `restaurant.menu.order()` +- Ignore invalid inputs: + - `console.log(menu.order(["burger", "fries", "pasta"])) // 8.5` diff --git a/2-javascript/assignments/js-assignment-7.md b/2-javascript/assignments/js-assignment-7.md new file mode 100644 index 00000000..2ce3982d --- /dev/null +++ b/2-javascript/assignments/js-assignment-7.md @@ -0,0 +1,25 @@ +# JavaScript Assignment #7: Classes + +You will complete all of these challenges in the same file. + +## Challenge #1: Create a class + +- Create a new class `BankAccount` with attributes `ownerName` and `balance` + - `ownerName` should be passed in to the constructor + - `balance` should be initialized as `0` +- Create a new instance of the class for an imaginary person, `person` + +## Challenge #2: Create class methods + +- Create a method `deposit` that takes one argument, `amount`. The method should increase the balance by that amount. +- Call `person.deposit(100)` and then console log `person.balance`. It should say 100. +- Now do the same, with a `withdaw` method that reduces the balance. + + - Don't let people overdraft! Have the `withdraw` method first check the balance, and if there isn't enough money, cancel the transaction and print a message that says "Insufficient Funds" + +#### Extra challenges (optional) + +- What happens if you give the deposit and withdraw methods arguments that are not numbers? Can you handle those cases? +- What happens if you pass a negative number to the `deposit` method? Can your method detect that situation, and call `this.withdraw` instead? (Math.abs() might help you here.) +- Can you keep a log of the user's transactions? Try storing this information in whatever way seems appropriate to you. + - How about a `printTransactions` method that gives the users a nicely formatted list of transations? diff --git a/2-javascript/assignments/js-assignment-8.md b/2-javascript/assignments/js-assignment-8.md new file mode 100644 index 00000000..46e6a502 --- /dev/null +++ b/2-javascript/assignments/js-assignment-8.md @@ -0,0 +1,45 @@ +# JavaScript Assignment #8: Callbacks + +You will complete all of these challenges in the same file. + +## Challenge #1: Practice .filter() + +- Make an array with the numbers 1 - 10 +- Use `.filter()` to create an array with only numbers that are larger than 7 +- Use `.filter()` to create an array with only numbers that are even +- Use `.filter()` to create an array with only numbers that are divisible by 3 + +## Challenge #2: Practice .map() + +Using that same array with number 1-10 + +- Use `.map()` to create an array with the square of each number (such as `[1, 4, 9, 16...]`) +- Use `.map()` to create an array with each number halved (such as `[0.5, 1, 1.5...]`) + +## Challenge #3: Using .filter() to filter objects + +Start by pasting this into your code: + +```javascript +const prices = [ + { product: "shoes", price: 50, inStock: true }, + { product: "light bulb", price: 3, inStock: true }, + { product: "stuffed animal", price: 15, inStock: false }, + { product: "jacket", price: 75, inStock: false }, + { product: "keychain", price: 4, inStock: true }, +] +``` + +- Use `.filter()` to create an array with only the product objects that cost less than $20 +- Use `.filter()` to create an array with only the product objects that are in stock +- Use `.filter()` to create an array with only the product objects that are in stock AND cost less than $20 + +## Challenge #4: Using .map() to map objects + +- We're having a sale! Use `.map()` to create an array with all the same objects, but with the prices reduced by 25% +- The sale is only for products that cost more than $10. Rewrite the previous map to only change the prices for items with prices above $10. +- We're making an ad for the sale. Make an array of strings that read, for example, "shoes are on sale for only $37.50!" + +#### Extra challenges (optional) + +- Can you use `.reduce()` to join all the strings from the previous together into one long string? diff --git a/2-javascript/assignments/js-final-project.md b/2-javascript/assignments/js-final-project.md new file mode 100644 index 00000000..59fdc918 --- /dev/null +++ b/2-javascript/assignments/js-final-project.md @@ -0,0 +1,43 @@ +# Guess The Number + +## How the game works + +Before starting to code this project, please find a partner and play this game together verbally for a few rounds. + +1. Alice thinks of a number +2. Bob guesses a number +3. Alice says "higher", "lower", or "correct" +4. repeat 2 & 3 until Bob guesses correctly + +After you get a feel for the game, it's time to write a software version of the game, where the _human_ thinks of a number between 1 and 100 and the _computer_ tries to guess it. + +## Coding the game + +You will complete this project in a JavaScript file that you will run in the browser, via an HTML file. Get input from the user using `prompt()` and send messages to the user using `alert()` + +You will need to use loops and conditionals to make this program work. Technically you could complete it without any functions, but I strongly recommend using functions to keep your code tidy and organized. + +Gameplay will work like this: + +1. ask the user to choose a number between 1 and 100 +1. ask the user something like "is the number higher than, lower than, or exactly 50?" +1. continue asking that question, but modify the number based on their previous answers +1. when the user says you got the number right, end the game + +> The best way to narrow down your guesses is by using the binary sort algorithm. [This Khan Academy article](https://www.khanacademy.org/computing/computer-science/algorithms/intro-to-algorithms/a/a-guessing-game) explains the algorithm and gives a useful visualization. + +## Tips + +- to save the player (and you) from typing too much, offer the user the option to answer `h` (for higher), `l` (for lower), or `c` for correct +- off-by-one errors are a risk here. Double check the distinction betweens "greater than" and "greater than or equal to", and "less than" and "less than or equal to" +- sign reversal errors are also a common mistake. Make sure you're not using `>` when you should be using `<`, and vice versa +- when you feel like your game is close to ready, ask someone to play it. Watching them play is a great way to spot bugs, poor UX, and other issues with the program + +## Extra challenges (optional) + +- keep track of the number of guesses we needed, and display a message with that number at the end of the game +- handle invalid/unexpected inputs from the user +- when the game is over, ask the user if they want to play again, and if so play another round. (Hint: this requires a while loop.) +- write a version of the game in which the computer chooses the number, the user guesses numbers, and the computer answers whether the guess is higher or lower + - if you finish that and want more, make the program start by giving the user a choice between the two games, and then start the game they ask for + - ... and then ask again at the end of each round diff --git a/2-javascript/callbacks.js b/2-javascript/callbacks.js new file mode 100644 index 00000000..d7a9dd5a --- /dev/null +++ b/2-javascript/callbacks.js @@ -0,0 +1,103 @@ +/* + ? Callbacks + * a function that is passed as an argument to another function + * JS uses these more than any other language + * very useful for asynchronicity + * which is really important for web apps +*/ + +/* + ? Function Expressions + * work exactly the same as Function Declarations + * except that they're not hoisted (we'll come back to this idea) + * more flexible syntax + * old school + * ES6 + * Can be anonymous +*/ + +// function declaration +function newFunction() { + return null; +} + +// function expression, old school +const newerFunction = function () { + return null; +}; + +// function expression, ES6 syntax +const newestFunction = () => { + return null; +}; + +// concise syntax (works for either type of function expression) +// if you have exactly one parameter, the parens are optional +// if the return value fits on one line +// you can lose the curly brackets +// AND the return statement + +const add = (x, y) => x + y; +const subtract = (x, y) => x - y; +const double = (x) => x * 2; // these parens are optional + +console.log(add(1, 2)); +console.log(double(5)); + +const doMath = (a, b, mathFunc) => { + return mathFunc(a, b); +}; + +console.log(doMath(4, 8, add)); +console.log(doMath(4, 8, subtract)); + +// callback with anonymous function +// anonymous means it's never named, never assigned to a variable +console.log(doMath(5, 7, (a, b) => a * b)); + +/* + ? Map, Filter, Reduce + Array methods that take callbacks + return new arrays, leave the original alone +*/ + +const nums = [1, 2, 3, 4, 5]; + +// .map() performs the callback on every element in the array +// the callback args are +// element: the element of the array +// (optional) index: the index of the array +// (optional) array: the whole original array object + +// const doubledNums = nums.map(double); +const doubledNums = nums.map((x) => x * 2); +console.log(doubledNums); + +// .filter() returns a new array that includes only elements that pass the test +// the callback must return a boolean +// if true, the element will be added to the new array +// if false, the element will be ignored + +// const oddNums = nums.filter((x) => { +// if (x % 2 == 1) { +// return true; +// } +// return false; +// }); + +const oddNums = nums.filter((x) => x % 2 == 1); +console.log(oddNums); + +const smallNums = nums.filter((x) => x < 3); +console.log(smallNums); + +// .reduce() creates a singular new value, based on all the elements of the array +// the callback args are +// * accumulated value +// * each element in the array +// reduce has an optional second arg for starting value +const sum = nums.reduce( + (accumulatedValue, arrayElement) => accumulatedValue + arrayElement, + 10 // this argument sets the starting value for the accumulated value +); +console.log(sum); // 25 diff --git a/2-javascript/classes.js b/2-javascript/classes.js new file mode 100644 index 00000000..a614df95 --- /dev/null +++ b/2-javascript/classes.js @@ -0,0 +1,64 @@ +class Medal { + constructor(sport, level, year) { + this.sport = sport; + this.level = level; + this.year = year; + } +} + +class Olympian { + constructor(fullName, sport, country) { + this.name = fullName; + this.sport = sport; + this.country = country; + this.yearsCompeted = []; + this.medals = []; + } + + describe() { + return `${this.name} is an athlete in the sport of ${this.sport}. \ +She has competed in ${this.yearsCompeted.length} Olympics. \ +She has won ${this.medals.length} medals. + `; + } + + compete(year, medal) { + if (medal) { + const newMedal = new Medal(this.sport, medal, year); + this.medals.push(newMedal); + } + + if (!this.yearsCompeted.includes(year)) { + this.yearsCompeted.push(year); + } + } +} + +const faith = new Olympian("Faith Kipyegon", "running", "Kenya"); +const katie = new Olympian("Katie Ledecky", "swimming", "USA"); +const simone = new Olympian("Simone Biles", "gymnastics", "USA"); + +// faith.yearsCompeted.push(2012, 2016, 2020); +faith.compete(2012); +faith.compete(2016, "gold"); +faith.compete(2020, "gold"); + +katie.compete(2012, "gold"); + +katie.compete(2016, "gold"); +katie.compete(2016, "gold"); +katie.compete(2016, "gold"); +katie.compete(2016, "gold"); +katie.compete(2016, "silver"); + +katie.compete(2020, "gold"); +katie.compete(2020, "gold"); +katie.compete(2020, "silver"); +katie.compete(2020, "silver"); +katie.compete(2020); + +console.log(katie); +console.log(katie.describe()); + +console.log(faith); +console.log(faith.describe()); diff --git a/2-javascript/coercion.js b/2-javascript/coercion.js new file mode 100644 index 00000000..f9a86468 --- /dev/null +++ b/2-javascript/coercion.js @@ -0,0 +1,35 @@ +// TYPE COERCION + +// constructors +// you can use the Type constructors to create new values + +// these two are the same +let newString1 = "any string" +let newString2 = String("any string") +console.log(newString1) + +let newNumber = Number(123) +let newArray = Array([1, 2, 3], 4, 5) // takes any number of comma separated arguments +console.log(newArray) + +// change types explicitly, using the type constructor +// usually called type casting +// also called type conversion + +newString1 = Array(newString1) +console.log(newString1) // ["any string"] + +newNumber = String(newNumber) +console.log(newNumber.length) // this is a string so we can do string stuff to it! + +let output = Number([12, 34]) +console.log(output) + +let newString3 = Number("123abc") +console.log(newString3) // NaN + +// implicit coercion + +console.log(1 + "2") // 12 - concatenation! coerces the number to a string +console.log(3 * "2") // 6 - multiplication! coerces the string to a number +console.log(3 * "two") // NaN, "two" can't be coerced to a number diff --git a/2-javascript/conditionals.js b/2-javascript/conditionals.js new file mode 100644 index 00000000..a8feeead --- /dev/null +++ b/2-javascript/conditionals.js @@ -0,0 +1,60 @@ +// CONDITIONAL +// a code block that only executes under certain conditions + +// anything inside the parentheses will be evaluated as a boolean expression +let condition +if (condition) { + // inside the curly brackets is called a "code block" + // in conditionals, the code block only executes of the condition is true + pass +} + +if (1) { + console.log("one is truthy, so this log will happen") +} + +if ("") { + console.log("empty string is falsey so this log won't happen") +} + +let temperature = 110 +let rainy = false + +// when writing complex conditionals +// it can be helpful to break some sets of conditions out +// into their own variables +let isWarmAndWet = temperature >= 70 && rainy +let isDryandCold = !rainy && temperature < 65 + +if (temperature < 65 && rainy) { + console.log("Danny is grumpy!") +} else if (isWarmAndWet || isDryandCold) { + // the "else if" executes if + // ... the previous code block did NOT execute + // ... and the condition is true + console.log("Danny is okay") +} else { + // the "else" executes if all of the previous code blocks didn't + // it has no extra conditions + console.log("Danny is happy!") +} + +// this one could almost be a switch statement +// but switch statements are generally looking for specific values, not ranges +if (temperature > 100) { + console.log("I'm melting") +} else if (temperature > 80) { + // note that because only one of the code blocks will execute + // we don't have to specify that the temperature has to be less than 100 + // if it had been over 100, the first block would have executed + // and this one wouldn't even happen + console.log("it's pretty hot") +} else if (temperature > 65) { + console.log("it is pretty nice out!") +} else if (temperature > 35) { + console.log("at least it's not freezing") +} else if (temperature > 15) { + console.log("it's cold out!") +} else { + console.log("IT IS WAY WAY TOO COLD") +} diff --git a/2-javascript/data-types/arrays.js b/2-javascript/data-types/arrays.js new file mode 100644 index 00000000..084a936a --- /dev/null +++ b/2-javascript/data-types/arrays.js @@ -0,0 +1,125 @@ +/* + ARRAYS + * list-like object + * reference data type + * hold multiple data types (literally anything that can be stored in JS) + * prototype has methods to perform traversal and mutation operations + * denoted by [ ] + * content can be accessed by their index +*/ + +// create a new array literal +// 0 1 2 3 4 +const nums = [1, 2, 3, 4, 5] + +// Length attribute +console.log(nums.length) // 5 + +// access by index +console.log(nums[2]) // 3 + +// ASSIGNMENT + +// assign by fixed index +nums[0] = "one" +nums[4] = "five" +nums[5] = "six" +nums[10] = "out of order" +// [ 'one', 2, 3, 4, 'five', 'six', _, _, _, _, 'out of order' ] +console.log(nums[8]) // undefined + +// assign by dynamic index +nums[nums.length] = "this goes at the end" + +// access by dynamic index and assign to a variable +let thirdPoint = nums[Math.floor(nums.length / 3)] +console.log(thirdPoint) // 'five' + +// We can reassign any (or all!) members of the array +// But we can't reassign the array itself, if it's declared with const +// nums = "[1, 2, 3]" // TypeError: Assignment to constant variable. + +// NESTED ARRAYS + +nums[8] = ["eight", "nine", "ten"] + +// This does the same thing.... +console.log(nums[8]) // ["eight", "nine", "ten"] + +// ... as this +const nestedArray = nums[8] +console.log(nestedArray[2]) // ["eight", "nine", "ten"] + +// ARRAY METHODS +const bestFoods = ["Jollof Rice", "Texas BBQ", "Chapati", "Sushi"] + +// changing (mutating) an array using array methods + +// Array.push() adds new elemends to the end and returns the new length +const output = bestFoods.push("Kuku") +console.log(output) // 5 + +bestFoods.push("Pasta", "Burgers", ["Salmon", "Shrimp", "Scallops"]) +console.log(output) // ["Jollof Rice", "Texas BBQ", "Chapati", "Sushi", "Kuku", "Pasta", "Burgers", ["Salmon", "Shrimp", "Scallops"]] + +// Array.pop() removes and returns the last element +const seafood = bestFoods.pop() +console.log(seafood) // [ 'Salmon', 'Shrimp', 'Scallops' ] +console.log(bestFoods) // (the seafood array has been removed) + +// Array.shift() removes and return the first element +const bestFish = seafood.shift() +console.log(bestFish) // "Salmon" +console.log(seafood) // [ 'Shrimp', 'Scallops' ] + +// Array.unshift() adds specified element to the beginning of an array +bestFoods.unshift(bestFish) +console.log(bestFoods) // (now Salmon is at the beginning) + +// ORDERING / INDEXING + +// Array.at() is just like access by index, except it can take negative numbers +console.log(bestFoods[1]) // "Jollof Rice" +console.log(bestFoods.at(1)) // same as above +console.log(bestFoods.at(-6)) // Texas BBQ (number 6 counting from the end) + +// Array.slice copies a portion of the array +const slice = bestFoods.slice(1, 3) +console.log(slice) + +// with no arguments, it copies the whole thing +const copy = bestFoods.slice() +console.log(copy) + +// with one argument, it slices from the given index to the end +const lastHalf = bestFoods.slice(4) +console.log(lastHalf) + +const middle = bestFoods.slice(3, 6) +console.log(middle) + +// SORTING + +// Array.toSorted makes a sorted copy + +const sortedCopy = bestFoods.toSorted() +console.log(sortedCopy) +console.log(bestFoods) + +// Array.sort() sorts an array IN PLACE! + +const whatIsThis = bestFoods.sort() +console.log(whatIsThis) // this is just the same thing, it's not really necessary + +// Array.reverse() reverses ar array IN PLACE +bestFoods.reverse() + +// Array.indexOf() finds the index of the FIRST instance +bestFoods[4] = "Sushi" +console.log(bestFoods) + +const sushiIndex = bestFoods.indexOf("Sushi") +console.log(sushiIndex) + +const sushiIndex2 = bestFoods.indexOf("Sushi", 3) +console.log(sushiIndex2) diff --git a/2-javascript/data-types/booleans.js b/2-javascript/data-types/booleans.js new file mode 100644 index 00000000..6b30e8e1 --- /dev/null +++ b/2-javascript/data-types/booleans.js @@ -0,0 +1,89 @@ +/* + BOOLEANS + * store a binary value + * true, false + * boolean expressions evaluate to true or false + * JS leans heavily on "truthy" and "falsey" +*/ + +let isTrue = true +let isFalse = false +console.log(typeof isFalse) + +console.log(Boolean()) // false (by default) +console.log(Boolean(isTrue)) // true +console.log(Boolean(0)) // false +console.log(Boolean(1)) // true (all non-zero numbers are true) +console.log(Boolean(-1)) // true +console.log(Boolean(0.00000000000000000000000001)) // true +console.log(Boolean(NaN)) // false (this is the only member of the type Number, other than 0, that is false) + +console.log(Boolean("strings are truthy...")) // true +console.log(Boolean("")) // false (...except for empty string) +console.log(Boolean("false")) // true +console.log(Boolean("0")) // true + +console.log(Boolean([1, 2, 3])) // true +console.log(Boolean([])) // true (empty arrays are truthy) +console.log(Boolean({})) // true (same with empty objects, and all reference types) + +console.log(Boolean(undefined)) // false +console.log(Boolean(null)) // false + +// COMPARISON OPERATORS +// form boolean expressions, which resolve to true or false + +// = is the assignment operator +// == is the equality operator + +console.log(isFalse == false) // true +console.log(isFalse == 0) // true (because of type coercion) +console.log(isFalse == "") // true (because of type coercion) + +// the != operator is NOT equal + +console.log(isTrue != isFalse) // true +console.log(isTrue != 1) // false + +// === is the STRICT equality operator +// asks not only are they the same value, but are they also the same TYPE +// we use this one by default +// we only use == when we specifically want to rely on coercion + +console.log(isFalse === "") // false (not the same type!) +console.log(isTrue === 1) // false +console.log(isTrue === true) // true +console.log("same" === "same") // true + +console.log(isFalse !== "") // true +console.log(isTrue !== 1) // true +console.log(isTrue !== true) // false +console.log("same" !== "same") // false + +// no surprises here! +console.log(1 > 2) // false +console.log(1 < 2) // true +console.log(1 > 1) // false +console.log(1 >= 1) // true +console.log(1 <= 0) // false + +// CHAINING OPERATORS + +// && logical AND +console.log(isTrue == true && isFalse != 1) // true +console.log(isTrue == true && isFalse == 1) // false (both sides of the && have to be true) + +// you can combine as many expressions as you need! +console.log(isTrue == true && isFalse != 1 && "string" != "other string") // true +console.log(isTrue == true && isFalse != 1 && "string" != "string") // false + +// || logical OR +console.log(isTrue == true || isFalse != 1) // true +console.log(isTrue == true || isFalse == 1) // true (only one side of the || has to be true) + +const complexTrue = + (isTrue == 0 && "" === 0) || + (isFalse == 1 && isTrue == [] && 0 != 1) || + true // because only one side of the OR needs to be true, the whole expression will be true + +console.log(complexTrue) // true diff --git a/2-javascript/data-types/data-type-notes.md b/2-javascript/data-types/data-type-notes.md new file mode 100644 index 00000000..4b04b586 --- /dev/null +++ b/2-javascript/data-types/data-type-notes.md @@ -0,0 +1,28 @@ +# JavaScript Data Types + +## Primitive types + +A primitive type stores a single value. It is not an object, and has no properties or methods. There are exactly 7 primitive types: + +- string +- number (including NaN) +- boolean +- null +- undefined +- bigint (we'll never use these) +- symbol (we'll never use these) + +Though each data point has no properties or methods, the type itself has properties and methods which we can use to read or manipulate the data. + +## Reference types + +Reference types store references to collections of data, rather than single data points. + +There are a basically unlimited number of reference types, which are all, under the hood, different implementations of a JS object. The reference types we are most likely to see and use are: + +- object +- array +- function +- map +- set +- (and more) diff --git a/2-javascript/data-types/numbers.js b/2-javascript/data-types/numbers.js new file mode 100644 index 00000000..5c3894e3 --- /dev/null +++ b/2-javascript/data-types/numbers.js @@ -0,0 +1,52 @@ +const one = 1 +const two = 2 + +// basic arithmetic operators +console.log(1 + 2) +console.log(one + two) +console.log(1 - 2) +console.log(2 * 4) +console.log(5 / 2) + +// advanced arithmetic operators +console.log(4 ** 3) // exponent +console.log(19 % 5) // modulo, finds the remainder + +// BUILT-IN MATH OBJECT +console.log(Math.floor(19 / 5)) // this is floor division, floor rounds down +console.log(Math.ceil(Math.PI)) // ceiling, rounds up +console.log(Math.round(Math.SQRT1_2)) // rounds to nearest whole integer +console.log(Math.max(5, 2, 7, 14234, 9, 3)) // finds the highest value of the the given numbers +console.log(Math.min(5, 2, 7, 14234, 9, 3)) // finds the lowest value of the the given numbers + +// RANDOM NUMBERS +console.log(Math.random()) +// random number between zero and ten +const randomNum = Math.floor(Math.random() * 10) +console.log(randomNum) + +// fixed-point notation +console.log(Math.PI.toFixed(4)) // gives just four decimal places + +// other silly things +console.log(Number.MAX_SAFE_INTEGER) +console.log(Infinity * Number.MAX_SAFE_INTEGER) +console.log(Math.sqrt(-1)) // NaN (NotANumber), imaginary numbers are not built in to JS + +// CHAINING OPERATIONS + +console.log(6 * 8 + 3 - 1) + +// 6 times 3, plus 4, times 2, plus ten, divide by 3 = 18 + +console.log(6 * 3 + 4 * 2 + 10 / 3) // 29.999, not what we wanted! + +// avoid this by doing the operations on separate lines +let newNum = 6 * 3 +newNum = newNum + 4 +newNum = newNum * 2 + 10 +newNum = newNum / 3 +console.log(newNum) + +// or split it up using the grouping operator () +console.log(((6 * 3 + 4) * 2 + 10) / 3) diff --git a/2-javascript/data-types/object-methods.js b/2-javascript/data-types/object-methods.js new file mode 100644 index 00000000..3b78797f --- /dev/null +++ b/2-javascript/data-types/object-methods.js @@ -0,0 +1,84 @@ +const countries = { + us: "United States", + sa: "South Africa", + gh: "Ghana", + ng: "Nigeria", + ke: "Kenya", + gb: "Great Britain", + fr: "France", + + display() { + // loop through the properties of this object ("this") + for (country in this) { + // if the value isn't a function, log it + if (typeof this[country] !== "function") { + console.log(`${country}: ${countries[country]}`) + } + } + }, + + friendlyCompetition(country1, country2) { + // 'this' keyword refers to this whole object + // console.log(this) + + // if they are both valid countries + if (this._errorHandling(country1) && this._errorHandling(country2)) { + // randomly choose a winner + if (Math.random() > 0.5) { + return `${this[country1]} wins against ${this[country2]} in a friendly competition` + } + return `${this[country2]} wins against ${this[country1]} in a friendly competition` + } else { + return "Nice try though" + } + }, + + war(country1, country2) { + /* + psuedo-code + if country1 is france or great britain + return country2 wins + if country2 is france or great britain + return country1 wins + else friendlyCompetition(country1, 2) + */ + + if (country1 == "gb" || country1 == "fr") { + return `${this[country2]} wins against ${this[country1]}` + } else if (country2 == "gb" || country2 == "fr") { + return `${this[country1]} wins against ${this[country2]}` + } else { + return this.friendlyCompetition(country1, country2) + } + }, + + _errorHandling(countryCode) { + // starting a method name with an underscore is an indicator that it is "private" + // private methods are intended for use within the object, not to be accessed from outside + // some languages enforce this, JS will not (but it's still useful for communication) + if (Object.keys(this).includes(countryCode)) { + return true + } + console.log(`${countryCode} is not included in this directory`) + return false + }, +} + +console.log(this) // {} (this file, or "module", is an empty object) + +console.log(countries.display()) +console.log(countries.friendlyCompetition("sa", "us")) // random outcome (United States wins against South Africa in a friendly competition) +console.log(countries.war("ke", "gb")) // Kenya wins against Great Britain +console.log(countries.war("fr", "gh")) // Ghana wins against France +console.log(countries.war("ng", "gh")) // random outcome (Nigeria wins against Ghana in a friendly competition) + +console.log(countries.war("ng", "de")) // de is not included in this directory +// Nice try though + +console.log(countries._errorHandling("dn")) // dn is not included in this directory +// false + +// You can technically access methods with bracket notation +// but you usually won't +let battle = "war" +console.log(countries[battle]("sk", "pd")) diff --git a/2-javascript/data-types/objects.js b/2-javascript/data-types/objects.js new file mode 100644 index 00000000..5ba4e179 --- /dev/null +++ b/2-javascript/data-types/objects.js @@ -0,0 +1,190 @@ +/* + ? Objects + * containers for values + * organized by keys (also called "properties" or "attributes") + * iterable but not indexed + * { key: value, key2: value2 } + * comma separated key/value pairs, in curly brackets +*/ + +// keys can be any "valid JS identifier" +// or numbers, or any string +let exampleObject = { + key: "value", + key2: "value2", + key3: ["values", "can", "be", "any", "type"], + key4: { including: "nested objects" }, + _thing: 1, + $thing: 2, + 1: "numbers can be object keys", + "* any string can be an object key & @": 3, + [12]: "can arrays be keys?", +} + +/* + ? Accessing values by keys + + ? Dot notation + * requires that you know the key name (it can't be variable) + * requires a valid JS identifer as key (no numbers or strings) +*/ + +console.log(exampleObject._thing) +console.log(exampleObject.key4) +console.log(exampleObject.key4.including) // I can chain dot notation to access nested objects +console.log(exampleObject.key3[3]) // or access nested arrays by index, etc +console.log(exampleObject.key3[1].toUpperCase()) +// console.log(exampleObject.1) //SyntaxError + +/* + ? Bracket notation + * for when you can't use dot notation :) + * dynamic key names + * when keys are not valid JS identifiers +*/ + +console.log(exampleObject[1]) +console.log(exampleObject["* any string can be an object key & @"]) +console.log(exampleObject[[12]]) // apparently arrays with single values can be keys! + +let exampleKey = [12] +console.log(exampleObject[exampleKey]) +exampleKey = "* any string can be an object key & @" +console.log(exampleObject[exampleKey]) + +// the square brackets mean it will attempt to resolve to a value +// before looking up that value in the object +// with dot notation, it looks up that exact identifier as a key name +console.log(exampleObject.exampleKey) // undefined +// console.log(exampleObject[key3]) // ReferenceError: key3 is not defined + +/* + ? Destructuring + * use this when you want to save the value as a variable + * can get multiple keys out at the same time +*/ + +const { key } = exampleObject +// const key = exampleObject.key // does the same thing +console.log(key) + +const { key4, key2, key3 } = exampleObject +console.log(key4, key2, key3) + +// rename variable during destructring (does not change object) +const { _thing: one } = exampleObject +console.log(one) +// console.log(_thing) // ReferenceError: _thing is not defined + +/* + ? Modifying objects +*/ + +const countries = { + us: "United States", + sa: "South Africa", + gh: "Ghana", +} + +// assign new values with dot notation +countries.ng = "Nigeria" +// or with bracket notation (whether they are valid identifiers or not) +countries["ke"] = "Kenya" +countries["g b"] = "Great Britain" + +const france = "fr" +countries[france] = "France" + +// ? Overwrite existing values + +countries["g b"] = "War Losers" +countries.fr = "Even bigger losers" + +// ? Deleting key/value pairs + +// the delete operator +delete countries.fr +delete countries["g b"] + +console.log(countries) + +/* + ? Object methods + * used for accessing data + * Static methods, not instance methods + * meaning we call them on Object and pass the object as a param + * Object.keys() gives an array of keys + * Object.values() gives an array of values + * Object.entries() gives an array of arrays +*/ + +console.log(Object.keys(countries)) +console.log(Object.values(countries)) +console.log(Object.entries(countries)) + +/* + ? Looping over objects + * you can use a for..in loop + for (element in object) {code block} + * or you can loop over the keys, values, or entries +*/ + +// loops over keys +for (country in countries) { + // with bracket notation we can use variables to access the object + console.log(`${country}: ${countries[country]}`) +} + +// or turn them into arrays with the object methods +// and loop over with for..of +for (country of Object.values(countries)) { + // the keys don't exist here, we couldn't access them if we wanted to + console.log(country) +} + +for (country of Object.keys(countries)) { + console.log(`${country}: ${countries[country]}`) +} + +for (country of Object.entries(countries)) { + console.log(`${country[0]}: ${country[1]}`) +} + +/* + ? Deeply nested object + ? Complex data structure +*/ + +const habibi = { + name: "Habibi Park", + birthPlace: "Argentina", + parents: { + ma: { + name: "Sally Chin", + birthPlace: "Australia", + job: { + workplace: "USPS", + role: "postal delivery driver", + }, + }, + pa: { + name: "Ahmed Jones", + birthPlace: "Russia", + siblings: ["Martha", "Johannes", "Kim"], + }, + }, + hobbies: [ + "needle felting", + "motocross", + { sports: ["running", "rugby", "ice hockey"] }, + "baking", + ], +} + +console.log(habibi.parents.ma.birthPlace) // Australia +console.log(habibi.parents.mom) // undefined + +console.log(habibi.parents.pa.siblings[1]) // Johannes +console.log(habibi.hobbies[2]) // { sports: [ 'running', 'rugby', 'ice hockey' ] } +console.log(habibi.hobbies[2].sports) // [ 'running', 'rugby', 'ice hockey' ] +console.log(habibi.hobbies[2].sports[1]) // rugby diff --git a/2-javascript/data-types/strings.js b/2-javascript/data-types/strings.js new file mode 100644 index 00000000..14f6e16f --- /dev/null +++ b/2-javascript/data-types/strings.js @@ -0,0 +1,51 @@ +console.log("a string is text defined by quote marks") +console.log("strings can include any symbol you can type or paste") +console.log("@$)(*SLKJFWOI)($@()#$@$*(S+_!#)@$🙂🙂🙂") +console.log("My cat Hiccup says 'meow'") // include quotes in a string by using the other type of quotes +console.log('John\'s cat Hiccup says "meow"') // or escape special characters with a back slash +console.log("you can operate " + "on strings") // concatenation + +// STRING TEMPLATES +console.log(`string templates, or template strings, are defined by backticks`) +console.log(`string templates can include ' and " characters`) +console.log(`string templates have at least ${1 + 1} super powers`) // string interpolation +// you can put any valid JS code in between the curly brackets +// ONLY WORKS in string templates, not other types of strings +const me = "Danny" +const cat = "Hiccup" +const catSound = "meow" +console.log(`${me}'s cat ${cat} says "${catSound}"`) + +// STRING LITERAL VS INTERPOLATED STRING +const literal = "a string literal is a string exactly as written" +const templateLiteral = `template strings can be literal` +const concatenated = + "it stops being literal" + " " + "when you perform operations on it" +console.log(concatenated) +const interpolated = `or when you ${"operate inside"} the string template` +console.log(interpolated) + +// ATTRIBUTES +console.log("use dot notation to access attributes".length) //37 +console.log(cat.length) // 6 + +// STRING METHODS +const angryCat = cat.toUpperCase() +console.log(angryCat, cat, catSound) + +const catOuch = catSound.replace("ow", "ouch") +console.log(catSound) //meow (the original is not changed) +console.log(catOuch) //meouch + +// INDEXING +// indexing is referring to specific points in a string or array by its location +// location is identified by sequential integers +// starting with 0 + +// 0123456 +const abc = "abcdefg" +// access by index +console.log(abc[6]) //g + +console.log(catOuch.slice(2)) //ouch +console.log(catOuch.slice(2, 4)) //ou diff --git a/2-javascript/functions.js b/2-javascript/functions.js new file mode 100644 index 00000000..05c7bf8f --- /dev/null +++ b/2-javascript/functions.js @@ -0,0 +1,131 @@ +/* + ? FUNCTIONS + * a block of code that performs a particular task + * runs when invoked / called + * can be defined with a function declaration or a function expression + * we're learning declarations in class today + * + + Function declaration: + + function functionName(optional, parameters, aka, arguments) { + ... code block + } +*/ + +function sayHello() { + console.log("hello") +} + +sayHello() // invoking the function + +/* + ? Parameters + * params let you pass variable data into a function + * there is no technical limit to the number of params + * the variable you use to define the param + within the function defintion + is the variable that you will use to access it + from within the code block +*/ + +function greeting(personName) { + console.log(`hello ${personName}`) +} + +greeting("Wonder") +greeting("Jade") +greeting("Cilla") +greeting(["Benjamin", "Yadel", "Taiwo"]) +greeting(123, "Mercy") // hello 123 (it ignores extra values) +greeting() // hello undefined + +function add(num1, num2) { + console.log(num1 + num2) +} + +add(5, 4) // 9 +add(5, 4, 3) // 9 (extra values not used) +add(5) // NaN (it tried 5 + undefined) +// console.log(num1) // ReferenceError: num1 is not defined +// the function param names only exist within the function + +/* + ? Return values + * returns the output of a function + * by default, functions return undefined + * the function call is an expression that resolves to the return value + * defined with the return keyword + * the function STOPS when it gets to the return keyword +*/ + +function subtract(num1, num2) { + return num1 - num2 +} +console.log(subtract(1, 2)) // I have to log it to see the results + +// because the call is an expression that evaluates to the return value + +const newNumber = subtract(55, 23) +const anotherNumber = subtract(12, 5) +console.log(newNumber + anotherNumber) // these variables represent numbers now +// which means we can do math stuff to them +sayHello() + +// or you can use them as part of a larger expression +const newNum = subtract(3, 4) * subtract(5, 0) + subtract(10, 1) +console.log(newNum) + +// you can even use them inside other function calls +console.log(subtract(100, subtract(50, 10))) + +function introduction(name, location, hobby) { + console.log( + `Hello, my name is ${name}, I live in ${location} and I like to ${hobby}` + ) + return "this is the return value" + console.log("anything after the return won't happen") +} + +console.log(introduction(1, 2, 3)) // "this is the return value" +// the above line runs the log on line 83 AND also logs the function's return value + +// function parameters are positional +// meaning they are assgined to the param variables +// in the order they are listed when the function is called +introduction("Mary", "Tennessee", "play video games") +introduction("Riga", "make costumes", "Kira") // Hello, my name is Riga, I live in make costumes and I like to Kira +// if they are not all included, any that are missing will be undefined +introduction("Simon", "Maine") // Hello, my name is Simon, I live in Maine and I like to undefined + +// There is no technical limit to how complex the code inside a function can be! +function clock(hour, minute) { + // TODO: handle 0 hours + if (hour > 24 || hour < 0) { + return "That is not a valid hour" + } else if (minute >= 60 || minute < 0) { + return "That is not a valid minute" + } + + if (minute < 10) { + minute = "0" + minute + } + + // TODO: handle am/pm for 12 + let amPm = "am" + if (hour > 12) { + hour = hour - 12 + amPm = "pm" + } + return `${hour}:${minute} ${amPm}` +} + +// this loop will call our function each time through the loop! +for (let hour = 1; hour <= 24; hour++) { + for (let minute = 0; minute < 60; minute++) { + // we can use variables as parameters in the function call + console.log(clock(hour, minute)) + } +} + +console.log(clock(0, -5)) // That is not a valid minute diff --git a/2-javascript/loops.js b/2-javascript/loops.js new file mode 100644 index 00000000..2a2ce318 --- /dev/null +++ b/2-javascript/loops.js @@ -0,0 +1,78 @@ +/* + ? Loops + * execute a block of code repeatedly + * a loop keeps going until an exit condition is met + * exit conditions are sometimes explicit and sometimes implicit + * JS has many, many ways of writing a loop + * "for loops" are for when the number of times is pre-defined + * "while loops" are for when the number of times is unknown at the start +*/ + +let word = "antidisestablishmenarianism" + +let count = 0 +while (count < word.length) { + // something has to change about the condition each time + // otherwise we get an infinite loop + count++ // in this case, we increment the counter + console.log(`this loop happened ${count} times`) +} + +let num = 0 +while (num < 0.9) { + num = Math.random() + // in this case, the condition is based on a random number that will be different every time + console.log(num) +} + +// classic for loop +for (let i = 1; i <= 10; i++) { + console.log(i) +} + +for (let i = 3; i <= 1000; i) { + i = i ** 2 + console.log(i) +} + +// for..of loop +// for (element of iterable) {} + +// iterable means it can be iterated over, from "iteration" +// element is a new variable that we are creating on this line +// iterable is a variable that already exists somewhere + +for (letter of word) { + console.log(letter) + // logs a new line for each letter of the word +} + +const daysOfWeek = ["Mon", "Tues", "Wed", "Thurs", "Fri", "Sat", "Sun"] + +// a loop with a conditional in it +for (day of daysOfWeek) { + if (day === "Wed") { + console.log("Wednesday") + } else if (day === "Sat") { + console.log("Saturday") + } else { + console.log(`${day}day`) + } +} + +// a loop with a loop inside it +// a "nested loop" + +const vowels = "aeiou" + +let justVowels = "" +for (letter of word) { + // this layer of the loop (outer loop) is going over the whole word + for (v of vowels) { + // the inner loop goes all the way through the whole loop EVERY TIME + if (letter == v) { + justVowels += letter + } + } + console.log(justVowels) +} diff --git a/2-javascript/scope-and-hoisting.js b/2-javascript/scope-and-hoisting.js new file mode 100644 index 00000000..6bf112c5 --- /dev/null +++ b/2-javascript/scope-and-hoisting.js @@ -0,0 +1,113 @@ +displayName("Danny", "B") + +/* + ? Scope + * determines how information is accessible/available in different parts of the program + + Three levels of scope: + * global + * outermost scope + * accessible everywhere after declaration (from every other scope) + * within the same JS file (module) in node + * window object + * block + * within a code block + * introduced with ES6, with let and const + * function + * within a function +*/ + +// generally we avoid declaring variables in the global scope +const globalScopVar = "global" + +// UNLESS we want a global constant +const HOURS_IN_A_DAY = 24 +const MINUTES_IN_AN_HOUR = 60 + +// console.log(HOURS_IN_A_DAY * MINUTES_IN_AN_HOUR) + +function abc(param1) { + const functionScopeVar = "function scope" + console.log(param1) // this only exists here, inside the function + + if (true) { + const blockScopeVar = "block scope" + console.log(blockScopeVar) // only exists within this if statement + + if (true) { + const nestedBlockScopeVar = "nested block" + console.log(nestedBlockScopeVar) + console.log(functionScopeVar) + console.log(HOURS_IN_A_DAY) + } + } +} +// console.log(functionScopeVar) // ReferenceError: functionScopeVar is not defined + +// abc("parameter / argument") + +nums = [1, 2, 3] + +let total = 0 +for (num of nums) { + total += num +} +console.log(total) +// console.log(num) // this works but it's sloppy and kinda useless! + +function outerFx() { + const outerScopeVar = "outer function" + + function innerFx() { + const innerScopeVar = "inner function" + console.log(outerScopeVar) + } + // console.log(innerScopeVar) + innerFx() +} +// outerFx() + +/* + ? HOISTING + * the JS parsing engine reads top to bottom, left to right + * the JS interpreter reads the code twice + * first it looks for function declarations and vars and hoists them + * it allocates memory space to those declarations + * then it executes the code line by line + * function expressions, lets and consts are not hoisted + ! DO NOT RELY ON THIS +*/ + +// console.log(firstName) // ReferenceError: Cannot access 'firstName' before initialization +let firstName = "Danny" + +console.log(lastName) +var lastName = "Burrow" + +// displayName(firstName, lastName) + +function displayName(first, last) { + console.log(first, last) +} + +const sayHello = () => console.log("hello") +sayHello() + +/* + ? let/const vs var + * var is hoisted, let and const are not + * let and const can be block scoped + * var can only be function scoped or global +*/ + +const newFx = () => { + if (1) { + let letVar = 123 + var varVar = 432 + console.log(letVar) + } + console.log(varVar) +} +// console.log(varVar) + +newFx() diff --git a/2-javascript/variables.js b/2-javascript/variables.js new file mode 100644 index 00000000..51cec7a8 --- /dev/null +++ b/2-javascript/variables.js @@ -0,0 +1,77 @@ +/* + VARIABLES + * a variable represents one piece of data in memory + * in JS variables must be declared + * declaration + * allows memory space to be reserved using an identifier + * starts with keywords: let, const, or (archaic) var + * variable names must start with a letter, $, or _ + * if no value is assigned, it's undefined + * assignment + * gives the variable a data value + * can be any value or data type + * can be reassigned (unless declared with const) + * initialization + * giving a new variable its first value + * usually done on the same line as declaration + + Naming things is one of the two hard problems of computer science + * what makes a good variable name? + * JS variable names use camelCase + * first letter lowercase + * if there are multiple words + * first letter of subsequent words are capitalized + * names should describe either + * the data the variable stores, or + * the intended usage of that data + * longer is better than shorter (but not longer than necessary) + + Side note on casing: + Different case conventions are used in different situations + * kebab-case (we use this in html and css) + * camelCase (used for most things in JS) + * WordCase or PascalCase (used for certain things in JS) + * snake_case (used in Python) + * SCREAMING_SNAKE_CASE or CONSTANT_CASE (used in JS for constants) +*/ + +let a // declaration +console.log(a) //undefined + +a = "aaaaa" // assignment +console.log(a) //"aaaaa" + +a = 111111 // reassignment +console.log(a) //111111 + +let b = 222222 +console.log(b) + +console.log(a + b) //333333 +let c = a + b +console.log(c) //333333 + +let d = c +console.log(d) //333333 + +console.log("*********") +c + 100 +console.log(c) //333333 + +let e = c + 100 +console.log(e) //333433 + +c++ // c = c + 1 +console.log(c) //333334 +c++ +c++ +c++ +console.log(c) //333337 +// c = a + b +// console.log(c) //333333 + +console.log("*********") +console.log(d) + +const address = "123 Main St" +// address = "321 Main St" // TypeError: Assignment to constant variable. diff --git a/3-web-apis/alert-and-prompt/app.js b/3-web-apis/alert-and-prompt/app.js new file mode 100644 index 00000000..4c8d173d --- /dev/null +++ b/3-web-apis/alert-and-prompt/app.js @@ -0,0 +1,32 @@ +// if we run index.html in the browser, it will load this JS +// and log all of these console logs to the browser's console +console.log("hello world") + +const nums = [3, 4, 5] +const product = nums.reduce( + (acculumatedValue, element) => acculumatedValue * element +) +console.log(product) + +// ? Alert +// creates a small pop-up alert with a message in it +// it doesn't go away until the user dismisses it + +alert("this is a message to the user") + +// ? Prompt +// prompt gives the user a text input field +// and returns the text string they type in + +const answer = prompt("what is your answer to this question?") +// console.log(answer) + +// ? Responses will always be a string! +// remember to change the data type if you need to + +const num1 = Number(prompt("First number: ")) +const num2 = prompt("Second number: ") + +alert(num1 + Number(num2)) + +console.log(num1, num2) diff --git a/3-web-apis/alert-and-prompt/index.html b/3-web-apis/alert-and-prompt/index.html new file mode 100644 index 00000000..262024fb --- /dev/null +++ b/3-web-apis/alert-and-prompt/index.html @@ -0,0 +1,10 @@ + + + + + + Alert and Prompt + + + + diff --git a/3-web-apis/assignments/fetch/app.js b/3-web-apis/assignments/fetch/app.js new file mode 100644 index 00000000..7d70ed9a --- /dev/null +++ b/3-web-apis/assignments/fetch/app.js @@ -0,0 +1,66 @@ +// fetch returns a Promise object +// we can get the value out using resolvers... + +// fetch("https://jsonplaceholder.typicode.com/todos/5") +// .then((res) => res.json()) +// .then((json) => console.log(json)); + +// ... or handle the response with an async function +const getResponseJson = async () => { + const res = await fetch("https://jsonplaceholder.typicode.com/todos/5"); + console.log(res); + const json = await res.json(); + console.log(json); +}; +// getResponseJson(); + +/* + ? Show all pokemon! +*/ + +const contents = document.getElementById("contents"); +const startUrl = "https://pokeapi.co/api/v2/pokemon?limit=5"; + +const getPokemon = async (url) => { + const res = await fetch(url); + const data = await res.json(); + contents.innerHTML = ""; + makeButtons(data); + data.results.forEach((monster) => { + showPokemon(monster); + }); +}; + +const makeButtons = (data) => { + if (data.previous) { + const backButton = document.createElement("button"); + backButton.innerText = "Back"; + backButton.addEventListener("click", () => { + getPokemon(data.previous); + }); + contents.appendChild(backButton); + } + if (data.next) { + const nextButton = document.createElement("button"); + nextButton.innerText = "Next"; + nextButton.addEventListener("click", () => { + getPokemon(data.next); + }); + contents.appendChild(nextButton); + } +}; + +const showPokemon = async (pokemon) => { + const res = await fetch(pokemon.url); + const data = await res.json(); + + const header = document.createElement("h3"); + header.innerText = pokemon.name; + contents.appendChild(header); + + const sprite = document.createElement("img"); + sprite.src = data.sprites.front_default; + contents.appendChild(sprite); +}; + +getPokemon(startUrl); diff --git a/3-web-apis/assignments/fetch/index.html b/3-web-apis/assignments/fetch/index.html new file mode 100644 index 00000000..8238c9ed --- /dev/null +++ b/3-web-apis/assignments/fetch/index.html @@ -0,0 +1,12 @@ + + + + + + Pokemon! + + + +
+ + diff --git a/3-web-apis/assignments/web-assignment-1.md b/3-web-apis/assignments/web-assignment-1.md new file mode 100644 index 00000000..f3e0fa25 --- /dev/null +++ b/3-web-apis/assignments/web-assignment-1.md @@ -0,0 +1,34 @@ +# Web API Assignment #1: Dark mode, Light mode + +For the Web assignments, each assignment will need its own folder. You will place at least an `index.html` and `app.js` in this folder. Some assignments will also require CSS. + +### Dark mode, Light mode + +Start by pasting this code into the `body` of your HTML: + +```html +

Light Mode

+ + +``` + +1. In the JS, select all three of these elements using their ids and save them to variables. +1. Attach an event listener to the "dark" button that does the following things: + 1. change the `textContent` property of the banner to say "Dark Mode" + 1. change the `.style.color` property of the banner to be white + 1. change the `.style.backgroundColor` property of the `document.body` to be black +1. Repeat (but inverse) for the "light" button + +#### Extra challenges + +- Instead of black and white, change the colors to dark and light gray. (Easier on the eyes!) +- Add a CSS file with a class for dark mode. Instead of editing the style properties, toggle the class. +- Can you replace the two buttons with a single button? + - Start with the button saying "switch" + - Once that works, try changing the button to say "dark" or "light" depending on the mode + +#### Refreshers + +- Center the header and button on the page, both vertically and horizontally +- Change the font of the banner +- Give the buttons a font size of `1.5rem` and a padding of `0.5rem` diff --git a/3-web-apis/assignments/web-assignment-2.md b/3-web-apis/assignments/web-assignment-2.md new file mode 100644 index 00000000..a7a56f08 --- /dev/null +++ b/3-web-apis/assignments/web-assignment-2.md @@ -0,0 +1,33 @@ +# Web API Assignment #2: Fetching data + +### Make a to-do list with data from a remote API + +> Note: all of the to-do items in this database are lorem ipsum, their content does not matter for this exercise + +1. Create an HTML file, with `` in the body. +1. In a JS file, create an async function, and fetch all of the to-dos at this url: `https://jsonplaceholder.typicode.com/todos?userId=1` + - **note:** there are 10 users in this database, you could choose any userId between 1 and 10 for the url +1. For each to-do item in the data + 1. create an `
  • ` element + 1. set the text as the todo text + 1. append it to the `