diff --git a/.github/labeler.yml b/.github/labeler.yml index f1f3fe17cc7..b0958c5aea8 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -31,5 +31,9 @@ 'Content: Foundations': - 'foundations/**/*' +'Content: Markdownlint': + - 'markdownlint/**/*' + - '**/*.markdownlint-cli2.jsonc' + 'Type: Chore': - 'archive/**/*' diff --git a/.github/workflows/testing.yml b/.github/workflows/codespell.yml similarity index 94% rename from .github/workflows/testing.yml rename to .github/workflows/codespell.yml index b3fc0b46c42..9289a3e13c3 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/codespell.yml @@ -14,5 +14,4 @@ jobs: check_filenames: true check_hidden: true skip: ./.git,*.png,*.csv,./archive,./legacy_submissions - only_warn: 1 ignore_words_file: './.codespellignore' diff --git a/.github/workflows/markdownlint-lessons.yml b/.github/workflows/markdownlint-lessons.yml new file mode 100644 index 00000000000..604e456d619 --- /dev/null +++ b/.github/workflows/markdownlint-lessons.yml @@ -0,0 +1,34 @@ +name: MarkdownLint +on: + pull_request: + paths: + - '**.md' + - '!./*.md' + - '!**/project*.md' + - '!./archive/**.md' + - '!./templates/**.md' + - '!./markdownlint/docs/**.md' + +jobs: + lesson_lint: + name: Lint lesson files + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: tj-actions/changed-files@v41 + id: changed-files + with: + files: | + **.md + !./*.md + !README.md + !**/project*.md + !./archive/**.md + !./templates/**.md + !./markdownlint/docs/**.md + separator: ',' + - uses: DavidAnson/markdownlint-cli2-action@v14 + with: + config: './lesson.markdownlint-cli2.jsonc' + globs: ${{ steps.changed-files.outputs.all_changed_files }} + separator: ',' diff --git a/.github/workflows/markdownlint-projects.yml b/.github/workflows/markdownlint-projects.yml new file mode 100644 index 00000000000..6093ca8e69d --- /dev/null +++ b/.github/workflows/markdownlint-projects.yml @@ -0,0 +1,32 @@ +name: MarkDownLint +on: + pull_request: + paths: + - '**/project*.md' + - '!./*.md' + - '!./archive/**.md' + - '!./templates/**.md' + - '!./markdownlint/docs/**.md' + +jobs: + project_lint: + name: Lint project files + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: tj-actions/changed-files@v41 + id: changed-files + with: + files: | + **/project*.md + !./*.md + !README.md + !./archive/**.md + !./templates/**.md + !./markdownlint/docs/**.md + separator: ',' + - uses: DavidAnson/markdownlint-cli2-action@v14 + with: + config: './project.markdownlint-cli2.jsonc' + globs: ${{ steps.changed-files.outputs.all_changed_files }} + separator: ',' diff --git a/.github/workflows/markdownlint.yml b/.github/workflows/markdownlint.yml deleted file mode 100644 index e95a2e2c860..00000000000 --- a/.github/workflows/markdownlint.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: MarkdownLint -on: pull_request - -jobs: - project_lint: - name: Lint project files - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: tj-actions/changed-files@v41 - id: changed-files - with: - files: | - **/project*.md - !./*.md - !README.md - !./archive/**.md - !./templates/**.md - !./markdownlint/docs/**.md - separator: ',' - - uses: DavidAnson/markdownlint-cli2-action@v14 - if: steps.changed-files.outputs.any_changed == 'true' - with: - config: './project.markdownlint-cli2.jsonc' - globs: ${{ steps.changed-files.outputs.all_changed_files }} - separator: ',' - lesson_lint: - name: Lint lesson files - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: tj-actions/changed-files@v41 - id: changed-files - with: - files: | - **.md - !./*.md - !README.md - !**/project*.md - !./archive/**.md - !./templates/**.md - !./markdownlint/docs/**.md - separator: ',' - - uses: DavidAnson/markdownlint-cli2-action@v14 - if: steps.changed-files.outputs.any_changed == 'true' - with: - config: './lesson.markdownlint-cli2.jsonc' - globs: ${{ steps.changed-files.outputs.all_changed_files }} - separator: ',' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b662bf93126..85eee72bc65 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,4 +31,11 @@ To help enforce the layout specified in our layout style guide, we use [markdown - Lint projects: `npm run lint:project -- "./path/to/project"` - Autofix projects: `npm run fix:project -- "./path/to/project"` -With either of these two methods, keep in mind that not all issues that get flagged will have an autofix available. Some rules require fixes that are more dependent on context and cannot - and should not - be automatically fixed, such as our custom rule `TOP001` for descriptive link text. +> [!IMPORTANT] +> You *must* run these npm scripts in the root of the curriculum repo (the same location as this file and `package.json`). If you navigate to a different directory and run a script on files there, it will not pick up the right configuration files and rules. + +> [!TIP] +> In some cases, you may need to run a fix script more than once to catch and fix all fixable errors. This typically occurs when a line has multiple errors affecting the same parts and fix actions collide, so Markdownlint only applies some of the fixes. + +> [!NOTE] +>With either of these two methods, keep in mind that not all issues that get flagged will have an autofix available. Some rules require fixes that are more dependent on context and cannot - and should not - be automatically fixed, such as our custom rule `TOP001` for descriptive link text. diff --git a/README.md b/README.md index 9c61741316f..bb58f57138b 100644 --- a/README.md +++ b/README.md @@ -13,15 +13,17 @@ Our community can be found on the [TOP Discord server](https://discord.gg/fbFCkY The Odin Project depends on open-source contributions to improve, grow, and thrive. We welcome contributors of all experience levels and backgrounds to help maintain this awesome curriculum and community. If you would like to contribute to our curriculum, be sure to thoroughly read our [contributing guide](https://github.com/TheOdinProject/.github/blob/main/CONTRIBUTING.md). Some of the things you can do to contribute to our curriculum include: -* Correct typos and other grammar errors. -* Rewrite parts of existing lessons to make them clearer and easier to understand. -* Fix broken links. -* Add new resource links you think would make a lesson better. -* Work on entirely new lessons after getting approval. + +- Correct typos and other grammar errors. +- Rewrite parts of existing lessons to make them clearer and easier to understand. +- Fix broken links. +- Add new resource links you think would make a lesson better. +- Work on entirely new lessons after getting approval. **Happy Coding!** -\* See [license.md](https://github.com/TheOdinProject/curriculum/blob/main/license.md) for usage details. +See [license.md](https://github.com/TheOdinProject/curriculum/blob/main/license.md) for usage details. ___ -Created by [Erik Trautman](http://www.github.com/eriktrautman) \ No newline at end of file + +Created by [Erik Trautman](http://www.github.com/eriktrautman). diff --git a/advanced_html_css/accessibility/the_web_content_accessibility_guidelines_wcag.md b/advanced_html_css/accessibility/the_web_content_accessibility_guidelines_wcag.md index f253d7ca1a8..edf80a0e754 100644 --- a/advanced_html_css/accessibility/the_web_content_accessibility_guidelines_wcag.md +++ b/advanced_html_css/accessibility/the_web_content_accessibility_guidelines_wcag.md @@ -48,8 +48,10 @@ The second thing to keep in mind is that just taking those first few steps towar ### Assignment
+ 1. Read through the [WCAG Overview](https://www.w3.org/WAI/standards-guidelines/wcag/) page. Don't worry about all of the other links for now. The goal of reading this page is to understand more of the included overview and to get familiar with the site itself for when you *do* need to visit other pages on it. -2. Skim through [WebAIM's WCAG 2 Checklist](https://webaim.org/standards/wcag/checklist), keeping in mind to read the important disclaimer. For now the goal is just to get an idea of common accessibility issues, some of which you'll be ready to fix by the time you finish this set of lessons, rather than read through every issue listed on the page. Keep this resource bookmarked, though, as using it as your checklist when you start actively implementing accessibility will be really handy. +1. Skim through [WebAIM's WCAG 2 Checklist](https://webaim.org/standards/wcag/checklist), keeping in mind to read the important disclaimer. For now the goal is just to get an idea of common accessibility issues, some of which you'll be ready to fix by the time you finish this set of lessons, rather than read through every issue listed on the page. Keep this resource bookmarked, though, as using it as your checklist when you start actively implementing accessibility will be really handy. +
### Knowledge check @@ -63,4 +65,4 @@ The following questions are an opportunity to reflect on key topics in this less This section contains helpful links to related content. It isn't required, so consider it supplemental. -- It looks like this lesson doesn't have any additional resources yet. Help us expand this section by contributing to our curriculum. +- [The A11Y Project](https://www.a11yproject.com/): An open-source resource that provides information on how to make your web content more accessible. The A11Y Project includes checklists, guidelines, and tools that can help you implement WCAG standards effectively. diff --git a/advanced_html_css/animation/transforms.md b/advanced_html_css/animation/transforms.md index 39ff1a5f34c..76e79c8d29f 100644 --- a/advanced_html_css/animation/transforms.md +++ b/advanced_html_css/animation/transforms.md @@ -157,7 +157,9 @@ on CodePen. -If you guessed correctly, congratulations! But this is a tricky concept. There is a bit of debate on how to read a chain of transform functions. According to [MDN's transform docs](https://developer.mozilla.org/en-US/docs/Web/CSS/transform#values): "The transform functions are multiplied in order from left to right, meaning that composite transforms are effectively applied in order from right to left." +If you guessed correctly, congratulations! But this is a tricky concept. MDN's transform docs state that "[composite transforms are effectively applied in order from right to left](https://developer.mozilla.org/en-US/docs/Web/CSS/transform#values)". + +The blue box rotates 45 degrees on the spot, then translates on the X axis by 200%, moving it directly to the right. The red box translates by 200% first, so moves to the right, but the transform origin is still where it used to be. Therefore, it rotates 45 degrees around that original point, making the red box "swing down" to end up diagonally from where it started. While you can generally chain multiple transforms in any order for various results, there is one exception: `perspective`. This brings us nicely to the next section where `perspective` is involved. @@ -269,7 +271,7 @@ Another benefit of `transform` is that it can be hardware-accelerated via a devi
-1. Take a look at this [MDN demonstration of `rotate3d`](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate3d()) then read more about the property in this [Quackit article on `rotate3d`](https://www.quackit.com/css/functions/css_rotate3d_function.cfm). +1. Take a look at this [MDN demonstration of `rotate3d`](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate3d()) then read more about the property in this [Quackit article on `rotate3d`](https://www.qhmit.com/css/functions/css_rotate3d_function.cfm). 1. Learn more about [the `perspective` property on CSS Tricks](https://css-tricks.com/how-css-perspective-works/). 1. MDN has another great [demonstration using `translate3d`](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translate3d()). 1. Go through [The World of CSS Transforms](https://www.joshwcomeau.com/css/transforms/) by Josh Comeau. diff --git a/advanced_html_css/animation/transitions.md b/advanced_html_css/animation/transitions.md index 2da8649998a..7c303fe37ca 100644 --- a/advanced_html_css/animation/transitions.md +++ b/advanced_html_css/animation/transitions.md @@ -24,7 +24,7 @@ CSS transitions let you animate a change from an element's initial state to an e -When your mouse cursor is away from the button, the button is in the initial state. When you hover over it you introduce the end state, the hover state, causing the transition of the color smoothly fading from white to black to occur. +When your mouse cursor is away from the button, the button is in the initial state. When you hover over it, you introduce the end state - the hover state - causing the background color to transition smoothly from white to black. This was achieved using the `transition` property, which is actually a shorthand property for `transition-property`, `transition-duration`, `transition-timing-function` and `transition-delay`. diff --git a/nodeJS/authentication/security_configuration.md b/archive/nodeJS/authentication/security_configuration.md similarity index 100% rename from nodeJS/authentication/security_configuration.md rename to archive/nodeJS/authentication/security_configuration.md diff --git a/nodeJS/express_and_mongoose/deployment.md b/archive/nodeJS/express_and_mongoose/deployment.md similarity index 100% rename from nodeJS/express_and_mongoose/deployment.md rename to archive/nodeJS/express_and_mongoose/deployment.md diff --git a/nodeJS/express_and_mongoose/express_101.md b/archive/nodeJS/express_and_mongoose/express_101.md similarity index 100% rename from nodeJS/express_and_mongoose/express_101.md rename to archive/nodeJS/express_and_mongoose/express_101.md diff --git a/nodeJS/express_and_mongoose/express_102_crud_and_mvc.md b/archive/nodeJS/express_and_mongoose/express_102_crud_and_mvc.md similarity index 100% rename from nodeJS/express_and_mongoose/express_102_crud_and_mvc.md rename to archive/nodeJS/express_and_mongoose/express_102_crud_and_mvc.md diff --git a/nodeJS/express_and_mongoose/express_103_routes_and_controllers.md b/archive/nodeJS/express_and_mongoose/express_103_routes_and_controllers.md similarity index 100% rename from nodeJS/express_and_mongoose/express_103_routes_and_controllers.md rename to archive/nodeJS/express_and_mongoose/express_103_routes_and_controllers.md diff --git a/nodeJS/express_and_mongoose/express_104_view_templates.md b/archive/nodeJS/express_and_mongoose/express_104_view_templates.md similarity index 100% rename from nodeJS/express_and_mongoose/express_104_view_templates.md rename to archive/nodeJS/express_and_mongoose/express_104_view_templates.md diff --git a/nodeJS/express_and_mongoose/introduction_to_express.md b/archive/nodeJS/express_and_mongoose/introduction_to_express.md similarity index 100% rename from nodeJS/express_and_mongoose/introduction_to_express.md rename to archive/nodeJS/express_and_mongoose/introduction_to_express.md diff --git a/nodeJS/express_and_mongoose/project_express_105_forms_and_deployment.md b/archive/nodeJS/express_and_mongoose/project_express_105_forms_and_deployment.md similarity index 100% rename from nodeJS/express_and_mongoose/project_express_105_forms_and_deployment.md rename to archive/nodeJS/express_and_mongoose/project_express_105_forms_and_deployment.md diff --git a/nodeJS/express_and_mongoose/project_inventory_application.md b/archive/nodeJS/express_and_mongoose/project_inventory_application.md similarity index 100% rename from nodeJS/express_and_mongoose/project_inventory_application.md rename to archive/nodeJS/express_and_mongoose/project_inventory_application.md diff --git a/nodeJS/express_and_mongoose/project_mini_message_board.md b/archive/nodeJS/express_and_mongoose/project_mini_message_board.md similarity index 100% rename from nodeJS/express_and_mongoose/project_mini_message_board.md rename to archive/nodeJS/express_and_mongoose/project_mini_message_board.md diff --git a/nodeJS/mongoDB/intro_to_mongoDB.md b/archive/nodeJS/mongoDB/intro_to_mongoDB.md similarity index 100% rename from nodeJS/mongoDB/intro_to_mongoDB.md rename to archive/nodeJS/mongoDB/intro_to_mongoDB.md diff --git a/databases/databases/databases.md b/databases/databases/databases.md index 94da2159c73..838462511df 100644 --- a/databases/databases/databases.md +++ b/databases/databases/databases.md @@ -1,6 +1,6 @@ ### Introduction -We've talked about the client-side and the server-side but how do we keep ahold of all our user's data? Who remembers that your login password is `CatLover1985` so you can sign into the website? The bottom layer of any web application is the database and it handles all the remembering for you (we'll cover caching much later). It can be relatively simple, like an Excel spreadsheet, or incredibly complex and split into many giant pieces, like Facebook's. +You might have wondered how you keep track of all your users' data. Who remembers that your login password is `CatLover1985` so you can sign into the website? The bottom layer of any web application is the database and it handles all the remembering for you (we'll cover caching much later). It can be relatively simple, like an Excel spreadsheet, or incredibly complex and split into many giant pieces, like Facebook's. Databases are kind of hidden in the back of the web application, so people approach them with a sense of suspicion and awe. However, do not fret or feel intimidated. As you dive deeper into the subject, your databases and you are going to become very good friends (or at least frenemies). Rest assured, by the end of this curriculum, you're going to understand what's going on with your databases and be able to interact with them like a pro (and probably better than some people you'll work with). This lesson is a teaser for that. @@ -10,41 +10,42 @@ Compared to a normal programming language like you've already learned, SQL (Stru This section contains a general overview of topics that you will learn in this lesson. -- What a database is. -- What relational databases are. -- In what way relational databases are different from XML. -- What SQL is. -- What SQL is used for. -- How to get all the records from a table in SQL. -- How to insert a record in SQL. +- What a database is. +- What relational databases are. +- In what way relational databases are different from XML. +- What SQL is. +- What SQL is used for. +- How to get all the records from a table in SQL. +- How to insert a record in SQL. ### Assignment
- 1. Check out this [introduction](https://launchschool.com/books/sql/read/introduction) of how SQL can be used to organise and manage an overwhelming amount of data. - - You do not need to go any further than the first page on introductions. + 1. Check out this introduction of [how SQL can be used to organise and manage an overwhelming amount of data](https://launchschool.com/books/sql/read/introduction). + - You do not need to go any further than the first page on introductions. - 2. Watch this [short video introduction to relational databases](http://www.youtube.com/watch?v=z2kbsG8zsLM) to get a feel for why this stuff is useful and some more exposure to the terminology we'll use. - 3. Go through this [Khan Academy tutorial](https://www.khanacademy.org/computing/hour-of-code/hour-of-sql/v/welcome-to-sql), to get a feel for actually creating and manipulating databases. + 1. Watch this [short video introduction to relational databases](http://www.youtube.com/watch?v=z2kbsG8zsLM) to get a feel for why this stuff is useful and some more exposure to the terminology we'll use. + 1. Go through this [Khan Academy SQL tutorial](https://www.khanacademy.org/computing/hour-of-code/hour-of-sql/v/welcome-to-sql) to get a feel for actually creating and manipulating databases.
### Knowledge check -This section contains questions for you to check your understanding of this lesson on your own. If you’re having trouble answering a question, click it and review the material it links to. -- [What is a database?](https://launchschool.com/books/sql/read/introduction#structureddata) -- [What are relational databases?](https://launchschool.com/books/sql/read/introduction#rdbms) -- [What is a Primary Key?](https://youtu.be/z2kbsG8zsLM?t=200) -- [What is SQL?](https://launchschool.com/books/sql/read/introduction#sql) -- [How do you get all the records from a table in SQL?](https://www.khanacademy.org/computing/hour-of-code/hour-of-code-lessons/hour-of-sql/pt/querying-the-table) -- [How do you insert a record in SQL?](https://www.khanacademy.org/computing/hour-of-code/hour-of-code-lessons/hour-of-sql/pt/creating-a-table-and-inserting-data) +The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. + +- [What is a database?](https://launchschool.com/books/sql/read/introduction#structureddata) +- [What are relational databases?](https://launchschool.com/books/sql/read/introduction#rdbms) +- [What is a Primary Key?](https://youtu.be/z2kbsG8zsLM?t=200) +- [What is SQL?](https://launchschool.com/books/sql/read/introduction#sql) +- [How do you get all the records from a table in SQL?](https://www.khanacademy.org/computing/hour-of-code/hour-of-code-lessons/hour-of-sql/pt/querying-the-table) +- [How do you insert a record in SQL?](https://www.khanacademy.org/computing/hour-of-code/hour-of-code-lessons/hour-of-sql/pt/creating-a-table-and-inserting-data) ### Additional resources -This section contains helpful links to related content. It isn’t required, so consider it supplemental. -- [What is a Relational Database?](http://computer.howstuffworks.com/question599.htm) from HowStuffWorks.com -- A brief [Simple Wiki article describing relational databases](http://simple.wikipedia.org/wiki/Relational_database) -- Hunter Ducharme created [an e-book](https://hunter-ducharme.gitbook.io/sql-basics/) which is a great documentation on how to do all the basics in SQL. -- David J. Malan's excellent SQL lecture and resources in [Harvard's CS50x](https://cs50.harvard.edu/x/2023/weeks/7/). -- Relational databases aren't the only way to store data. Non-relational (aka NoSQL) databases have emerged over the last couple decades. Check out [this article](https://circleci.com/blog/SQL-vs-NoSQL-databases/) to learn the difference between SQL and NoSQL. +This section contains helpful links to related content. It isn't required, so consider it supplemental. + +- [What is a Relational Database?](http://computer.howstuffworks.com/question599.htm) from HowStuffWorks.com +- A brief [Simple Wiki article describing relational databases](http://simple.wikipedia.org/wiki/Relational_database) +- [David J. Malan’s excellent SQL lecture](https://cs50.harvard.edu/x/2024/weeks/7/) and resources in Harvard’s CS50x. +- Relational databases aren't the only way to store data. Non-relational (aka NoSQL) databases have emerged over the last couple decades. Check out this article to learn the [difference between SQL and NoSQL](https://circleci.com/blog/SQL-vs-NoSQL-databases/). diff --git a/databases/databases/databases_and_sql.md b/databases/databases/databases_and_sql.md index 861d15f8c50..38875e67cc4 100644 --- a/databases/databases/databases_and_sql.md +++ b/databases/databases/databases_and_sql.md @@ -1,6 +1,6 @@ ### Introduction -Data is the core of any good web app and a good working knowledge of SQL will take you a long way. That knowledge lets you not just understand what's going on behind the scenes with your ORM tool (e.g. Active Record) but also to feel comfortable asking more complicated questions of your data. And that's really what SQL is all about -- asking questions of your database and occasionally also adding or changing things in it. Querying can be incredibly useful for you. +Data is the core of any good web app and a good working knowledge of SQL will take you a long way. That knowledge lets you not just understand what's going on behind the scenes with your ORM tool (e.g. Active Record in Rails, or Prisma in NodeJS) but also to feel comfortable asking more complicated questions of your data. And that's really what SQL is all about -- asking questions of your database and occasionally also adding or changing things in it. Querying can be incredibly useful for you. In more straightforward cases, you might want to display all users who signed up in December via the promotion code "FREESTUFF". You might want to display all comments created by the current user and sorted by topic and creation date. In more complex cases, you may want to show a list of all the orders shipped to states with more than 1,000 users by quantity and total order value. Or, for internal reasons, you might ask marketing analysis questions like which promotion channels produce users who meet your specified engagement criteria of reading 5 articles per work week. @@ -10,8 +10,7 @@ You will start with the questions like the ones above and then have to figure ou We'll move beyond just the `SELECT "users".* FROM "users" LIMIT 1` queries and into more dynamic topics like joining tables together, performing calculations on the results, and grouping results together in new ways. -All this stuff is being used by Rails behind the scenes so understanding it will make you much better at writing queries in Rails. This is why we're going over databases before learning Rails. - + #### A note on resources SQL is one of those topics that's been stored away in dusty old technical manuals and 90's style websites. Even the best books out there can make it seem oddly complicated because they tend to write for the database engineer who actually does need to know all the nitty gritty details. @@ -53,7 +52,7 @@ Once your database is set up and you've got empty tables to work with, you use S Every CRUDdy command in SQL contains a few parts -- the action ("statement"), the table it should run on, and the conditions ("clauses"). If you just do an action on a table without specifying conditions, it will apply to the whole database and you'll probably break something. -For "Destroy" queries, the classic mistake is typing `DELETE FROM users` without a `WHERE` clause, which removes all your users from the table. You probably needed to delete just one user, who you would specify based on some (hopefully unique) attribute like "name" or "id" as part of your condition clause, e.g. `DELETE FROM users WHERE users.id = 1`. You can do all kinds of common sense things like using `>`, `<`, `<=` etc. comparison operators to specify groups of rows to run commands on or logical operators like `AND`, `OR`, `NOT` etc to chain multiple clauses together, e.g. `DELETE FROM users WHERE id > 12 AND name = 'foo'`. +For "Destroy" queries, the classic mistake is typing `DELETE FROM users` without a `WHERE` clause, which removes all your users from the table. You probably needed to delete just one user, who you would specify based on some (hopefully unique) attribute like "name" or "id" as part of your condition clause, e.g. `DELETE FROM users WHERE users.id = 1`. You can do all kinds of common sense things, such as using comparison operators (`>`, `<`, `<=` etc.) to specify groups of rows to run commands on, or logical operators (`AND`, `OR`, `NOT` etc.) to chain multiple clauses together, e.g. `DELETE FROM users WHERE id > 12 AND name = 'foo'`. "Create" queries use `INSERT INTO` and you'll need to specify which columns to insert stuff into and then which values to put in those columns, which looks something like `INSERT INTO users (name, email) VALUES ('foobar','foo@bar.com');`. This is one of the few queries that you don't need to be careful about which rows you've selected since you're actually just adding new ones into the table. @@ -65,7 +64,7 @@ For "Destroy" queries, the classic mistake is typing `DELETE FROM users` without WHERE email='foo@bar.com'; ``` -"Read" queries, which use `SELECT`, are the most common, e.g. `SELECT * FROM users WHERE created_at < '2013-12-11 15:35:59 -0800'`. The `*` you see just says "all the columns". Specify a column using both the table name and the column name. You can get away with just the column name for queries of one table, but as soon as there are more than one table involved, SQL will yell at you so just always specify the table name: `SELECT users.id, users.name FROM users`. +"Read" queries, which use `SELECT`, are the most common, e.g. `SELECT * FROM users WHERE created_at < '2013-12-11 15:35:59 -0800'`. The `*` you see just says "all the columns". Specify a column using both the table name and the column name. You can get away with just the column name for queries of one table, but as soon as there is more than one table involved, SQL will yell at you so just always specify the table name: `SELECT users.id, users.name FROM users`. A close cousin of `SELECT`, for if you only want unique values of a column, is `SELECT DISTINCT`. Say you want a list of all the different names of your users without any duplicates... try `SELECT DISTINCT users.name FROM users`. @@ -80,9 +79,9 @@ The "left" table is the original table (the one that the `FROM` clause was `ON`)
1. `INNER JOIN`, aka `JOIN` -- Your best friend and 95% of what you'll use. Keeps only the rows from both tables where they match up. If you asked for all the posts for all users (`SELECT * FROM users JOIN posts ON users.id = posts.user_id`), it would return only the users who have actually written posts and only posts which have specified their author in the `user_id` column. If an author has written multiple posts, there will be multiple rows returned (but the columns containing the user data will just be repeated). -2. `LEFT OUTER JOIN` -- keep all the rows from the left table and add on any rows from the right table which match up to the left table's. Set any empty cells this produces to `NULL`. E.g. return all the users whether they have written posts or not. If they do have posts, list those posts as above. If not, set the columns we asked for from the "posts" table to `NULL`. -3. `RIGHT OUTER JOIN` -- the opposite... keep all rows in the right table. -4. `FULL OUTER JOIN` -- Keep all rows from all tables, even if there are mismatches between them. Set any mismatched cells to `NULL`. +1. `LEFT OUTER JOIN` -- keep all the rows from the left table and add on any rows from the right table which match up to the left table's. Set any empty cells this produces to `NULL`. E.g. return all the users whether they have written posts or not. If they do have posts, list those posts as above. If not, set the columns we asked for from the "posts" table to `NULL`. +1. `RIGHT OUTER JOIN` -- the opposite... keep all rows in the right table. +1. `FULL OUTER JOIN` -- Keep all rows from all tables, even if there are mismatches between them. Set any mismatched cells to `NULL`. Joins naturally let you specify conditions too, like if you only want the posts from a specific user: `SELECT * FROM users JOIN posts ON users.id = posts.user_id WHERE users.id = 42`. @@ -105,7 +104,7 @@ Now we're getting into the fun stuff. Aggregate functions like `COUNT` which re GROUP BY users.id; ``` -See [W3 Schools' article](http://www.w3schools.com/sql/trysql.asp?filename=trysql_select_groupby) and play around with the SQL in the window (try deleting the `GROUP BY` line) for an interactive visual. +See [W3Schools' browser-based SQL playground](http://www.w3schools.com/sql/trysql.asp?filename=trysql_select_groupby) for an interactive visual. The last nifty trick is if you want to only display a subset of your data. In a normal situation, you'd use a `WHERE` clause to narrow it down. But if you've used an aggregate function like `COUNT` (say to get the count of posts written for each user in the example above), `WHERE` won't work anymore. So to conditionally retrieve records based on aggregate functions, you use the `HAVING` function, which is essentially the `WHERE` for aggregates. So say you only want to display users who have written more than 10 posts: @@ -117,35 +116,37 @@ The last nifty trick is if you want to only display a subset of your data. In a HAVING posts_written >= 10; ``` -Try going back to [the W3 Schools' example](http://www.w3schools.com/sql/trysql.asp?filename=trysql_select_groupby) and joining the `Customers` and the `Orders` tables to get the number of orders in each country and adding the line `HAVING COUNT(*) > 10;` after `GROUP BY` (and delete the extra semicolon in the previous line). +Try going back to [W3Schools' browser-based SQL playground](http://www.w3schools.com/sql/trysql.asp?filename=trysql_select_groupby) and joining the `Customers` and the `Orders` tables to get the number of orders in each country and adding the line `HAVING COUNT(*) > 10;` after `GROUP BY` (and delete the extra semicolon in the previous line). You probably got lost somewhere in the above explanation and that's just fine... it's covering way more stuff than anyone can pick up in 10 minutes. The assigned reading will do a better job of explaining things but, more importantly, you'll get plenty of opportunities to solidify your understanding by applying it in the project. If you've still got blind spots, check out the Additional Resources section below. Fear not and stick with it! -### SQL is faster than Ruby! - -Learning this stuff is particularly relevant because it's MUCH faster for you to build queries that use SQL intelligently than to just grab a whole bunch of data out of your database and then use Ruby to process it. For instance, if you want all the unique names of your users, you COULD just grab the whole list from your database using SQL like `SELECT users.name FROM users` (which Active Record will do for you with `User.select(:name)`) then remove duplicates using Ruby's `#uniq` method, e.g. `User.select(:name).uniq`... but that requires you to pull all that data out of your database and then put it into memory and then iterate through it using Ruby. Use `SELECT DISTINCT users.name FROM users` instead to have SQL do it all in one step. +### SQL is faster than your code! -SQL is built to be fast. It has a special query optimizer which takes a look at the whole query you're about to run and it figures out exactly which tables it needs to join together and how it can most quickly execute the query. The difference between using `SELECT` and `SELECT DISTINCT` is negligible compared to the time cost of doing it in Ruby. Learning your SQL will help you write Active Record queries that can do more which will make your app much faster. +Learning this stuff is particularly relevant because it's MUCH faster for you to build queries that use SQL intelligently than to just grab a whole bunch of data out of your database and then use a programming language (like Ruby or JavaScript) to process it. For instance, if you want all the unique names of your users, you COULD just grab the whole list from your database using SQL like `SELECT users.name FROM users` then use a JavaScript/Ruby method to remove duplicates... but that requires you to pull all that data out of your database and then put it into memory and then iterate through it in your code. Use `SELECT DISTINCT users.name FROM users` instead to have SQL do it all in one step. +SQL is built to be fast. It has a special query optimizer which takes a look at the whole query you're about to run and it figures out exactly which tables it needs to join together and how it can most quickly execute the query. The difference between using `SELECT` and `SELECT DISTINCT` is negligible compared to the time cost of doing it yourself. Learning your SQL will help you write better queries that can do more which will make your app much faster. ### Assignment
- 1. Go through this interactive SQL tutorial from [SQL Teaching](https://www.sqlteaching.com/) - 2. Go through this more in-depth interactive SQL tutorial from [SQL Bolt](http://sqlbolt.com) - 3. Go through the basics at [Part 1](https://www.sqlcourse.com/beginner-course/) and the advanced at [Part 2](https://www.sqlcourse.com/advanced-course/) of SQL Course + + 1. Go through this [interactive SQL tutorial from SQL Teaching](https://www.sqlteaching.com/). + 1. Go through this more in-depth [interactive SQL tutorial from SQL Bolt](http://sqlbolt.com/). + 1. Go through [SQLCourse's beginner course](https://www.sqlcourse.com/beginner-course/) then [SQLCourse's advanced course](https://www.sqlcourse.com/advanced-course/). +
### Conclusion -SQL can be a tricky set of concepts to wrap your head around, particularly when it comes to conditionally displaying and grouping the results of multiple joins. We've emphasized that this stuff is useful for understanding what's going on behind the scenes with Rails and you'll get a chance to apply it in the project. Everything up to vanilla joins and vanilla aggregate functions is core knowledge that you should really make an effort to assimilate. +SQL can be a tricky set of concepts to wrap your head around, particularly when it comes to conditionally displaying and grouping the results of multiple joins. Everything up to vanilla joins and vanilla aggregate functions is core knowledge that you should really make an effort to assimilate. If you never quite get to the point where you're comfortable with the really advanced concepts, you'll luckily not need to use them except in a small fraction of situations in your future. It's good to learn it all up front but you'll probably find yourself Googling for how to perform certain advanced queries when the time comes anyway. -The next step, once you've had a chance to practice this all in the project, is to apply it to Rails with Active Record. You'll quickly find that Active Record makes your life much, much, much better. Just don't forget about ol' SQL when you've moved onto those better and brighter things, okay? +The next step, once you've had a chance to practice this all in the project, is to apply it to your codebase in the upcoming courses. You'll quickly find that using ORM tools makes your life much, much, much better. Just don't forget about ol' SQL when you've moved onto those better and brighter things, okay? ### Knowledge check -This section contains questions for you to check your understanding of this lesson on your own. If you’re having trouble answering a question, click it and review the material it links to. + +The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. - [What is the difference between a foreign key and a primary key?](#foreign-key) - [Where is the setup information for your database stored?](#schema) @@ -154,13 +155,14 @@ This section contains questions for you to check your understanding of this less - [Which `JOIN` statement keeps only the rows from both tables where they match up?](#inner-join) - [How do you use an aggregate function?](#aggregate-function) - [In which situation would you use the `HAVING` function?](#having-function) -- [Why can't I just use Ruby to process my database data?](#sql-is-faster-than-ruby) +- [Why can't I just use code to process my database data?](#sql-is-faster-than-your-code) ### Additional resources -This section contains helpful links to related content. It isn’t required, so consider it supplemental. -- Odinite Hunter D made his excellent notes into a [Git Book on SQL](https://hunter-ducharme.gitbook.io/sql-basics) which you should totally check out if you want a decent resource. -- [SQL "tutorial" from tutorialspoint](http://www.tutorialspoint.com/sql/index.htm)... doesn't really give much guidance, but can be a useful reference for the language. -- [A Beginners Guide to SQL](http://www.sohamkamani.com/blog/2016/07/07/a-beginners-guide-to-sql/) by Soham Kamani. -- [SQL Flashcards](https://flashcards.github.io/sql/introduction.html) by flashcards.github.io. -- If you feel like doing more SQL exercises, make sure to check out [SQL Exercises](http://www.sql-ex.com/). +This section contains helpful links to related content. It isn't required, so consider it supplemental. + +- Odinite Hunter D made his excellent notes into a [Git Book on SQL](https://hunter-ducharme.gitbook.io/sql-basics) which you should totally check out if you want a decent resource. +- [SQL "tutorial" from tutorialspoint](http://www.tutorialspoint.com/sql/index.htm)... doesn't really give much guidance, but can be a useful reference for the language. +- [A Beginners Guide to SQL](http://www.sohamkamani.com/blog/2016/07/07/a-beginners-guide-to-sql/) by Soham Kamani. +- [SQL Flashcards](https://flashcards.github.io/sql/introduction.html) by flashcards.github.io. +- If you feel like doing more SQL exercises, make sure to check out [SQL Exercises](http://www.sql-ex.com/). diff --git a/databases/databases/project_sql_zoo.md b/databases/databases/project_sql_zoo.md index 84ac7035120..984dc6095ba 100644 --- a/databases/databases/project_sql_zoo.md +++ b/databases/databases/project_sql_zoo.md @@ -5,16 +5,18 @@ SQL Zoo is one of the few resources online that actually lets you build and run ### Assignment
- 1. Go to [SQL Zoo](https://sqlzoo.net/) and do Tutorials 0-9 listed under the "Tutorial Section" and the quizzes listed at the end of each. The first is the ["Select" tutorial](https://sqlzoo.net/wiki/SELECT_basics). - - Make sure the dropdown on the upper right of the main page for "Engine" says "MySQL" (the default). Large results will be cut off and not all rows or columns shown, so the "answers" may not look 100% correct. - 2. Before you move on, we would like your feedback - [please fill this form](https://docs.google.com/forms/d/e/1FAIpQLSenvMG6WFbOOEap_biQOwqfbH-j-xsf5Eyv4ir2Rx5FsYSecQ/viewform?usp=sf_link). Getting user (you) feedback is important so we can continue to improve the curriculum and get an idea of your experience. + + 1. Go to [SQL Zoo](https://sqlzoo.net/) and do Tutorials 0-9 listed under the "Tutorial Section" and the quizzes listed at the end of each. The first tutorial is called "SELECT basics". + - Make sure the dropdown on the upper right of the main page for "Engine" says "MySQL" (the default). Large results will be cut off and not all rows or columns shown, so the "answers" may not look 100% correct. + 1. Before you move on, we would like your feedback - please fill out this [feedback form for the SQL course](https://docs.google.com/forms/d/e/1FAIpQLSenvMG6WFbOOEap_biQOwqfbH-j-xsf5Eyv4ir2Rx5FsYSecQ/viewform?usp=sf_link). Getting user (you) feedback is important so we can continue to improve the curriculum and get an idea of your experience. +
### Additional resources -This section contains helpful links to related content. It isn’t required, so consider it supplemental. +This section contains helpful links to related content. It isn't required, so consider it supplemental. -- [Explanation of SELF JOIN by Caleb Curry](https://www.youtube.com/watch?v=W0p8KP0o8g4). He covers many other topics on his [Database Design](https://www.youtube.com/watch?v=e7Pr1VgPK4w&list=PL_c9BZzLwBRK0Pc28IdvPQizD2mJlgoID) series. -- [Khan Academy's SQL Course](https://www.khanacademy.org/computing/computer-programming/sql) -- [OverAPI's SQL Cheat Sheet](http://overapi.com/mysql) -- [GalaXQL](http://sol.gfxile.net/galaxql.html), an interactive space-themed SQL tutorial. +- [Explanation of SELF JOIN by Caleb Curry](https://www.youtube.com/watch?v=W0p8KP0o8g4). He covers many other topics on his [Database Design](https://www.youtube.com/watch?v=e7Pr1VgPK4w&list=PL_c9BZzLwBRK0Pc28IdvPQizD2mJlgoID) series. +- [Khan Academy's SQL Course](https://www.khanacademy.org/computing/computer-programming/sql) +- [OverAPI's SQL Cheat Sheet](http://overapi.com/mysql) +- [GalaXQL](http://sol.gfxile.net/galaxql.html), an interactive space-themed SQL tutorial. diff --git a/foundations/html_css/css-foundations/block-and-inline.md b/foundations/html_css/css-foundations/block-and-inline.md index 06cb116c509..16e698b2be3 100644 --- a/foundations/html_css/css-foundations/block-and-inline.md +++ b/foundations/html_css/css-foundations/block-and-inline.md @@ -83,6 +83,6 @@ The following questions are an opportunity to reflect on key topics in this less This section contains helpful links to related content. It isn't required, so consider it supplemental. -- [Learn CSS Layout](https://learnlayout.com/no-layout.html) is tutorial that is a little dated at this point, but its examples are clear. The first 6 slides cover the material we've seen so far. +- [Learn CSS Layout](https://learnlayout.com/no-layout.html) is a tutorial that is a little dated at this point, but its examples are clear. The first 6 slides cover the material we've seen so far. - Watch this short video on [what the term “Normal Flow” means](https://www.youtube.com/watch?v=nfXRw06FgK8) in CSS. - For a more interactive explanation and example, try this [Scrim on block and inline display](https://scrimba.com/scrim/co5024997a7e46c232d9abe55). diff --git a/foundations/html_css/css-foundations/inspecting-html-and-css.md b/foundations/html_css/css-foundations/inspecting-html-and-css.md index 17e4d25be2b..3ca2ee3fb9b 100644 --- a/foundations/html_css/css-foundations/inspecting-html-and-css.md +++ b/foundations/html_css/css-foundations/inspecting-html-and-css.md @@ -1,6 +1,6 @@ ### Introduction -Being able to inspect and debug your HTML and CSS is critical to frontend development. This lesson will take us through the Chrome Dev Tools, which allow you to see detailed information about your elements and CSS rules, as well as assist you in finding and fixing problems in your code. +Being able to inspect and debug your HTML and CSS is critical for frontend development. This lesson will take us through the Chrome Dev Tools, which allow you to see detailed information about your elements and CSS rules, as well as assist you in finding and fixing problems in your code. ### Lesson overview diff --git a/foundations/html_css/css-foundations/intro-to-css.md b/foundations/html_css/css-foundations/intro-to-css.md index fee21686b2d..46ba2b6377f 100644 --- a/foundations/html_css/css-foundations/intro-to-css.md +++ b/foundations/html_css/css-foundations/intro-to-css.md @@ -283,7 +283,7 @@ Now that we've learned some basic syntax, you might be wondering *how* to add al #### External CSS -External CSS is the most common method you will come across, and it involves creating a separate file for the CSS and linking it inside of an HTML's opening and closing `` tags with a self-closing `` element: +External CSS is the most common method you will come across, and it involves creating a separate file for the CSS and linking it inside of an HTML's opening and closing `` tags with a void `` element: ```html @@ -306,7 +306,7 @@ p { } ``` -First, we add a self-closing `` element inside of the opening and closing `` tags of the HTML file. The `href` attribute is the location of the CSS file, either an absolute URL or, what you'll be utilizing, a URL relative to the location of the HTML file. In our example above, we are assuming both files are located in the same directory. The `rel` attribute is required, and it specifies the relationship between the HTML file and the linked file. +First, we add a void `` element inside of the opening and closing `` tags of the HTML file. The `href` attribute is the location of the CSS file, either an absolute URL or, what you'll be utilizing, a URL relative to the location of the HTML file. In our example above, we are assuming both files are located in the same directory. The `rel` attribute is required, and it specifies the relationship between the HTML file and the linked file. Then inside of the newly created `styles.css` file, we have the selector (the `div` and `p`), followed by a pair of opening and closing curly braces, which create a "declaration block". Finally, we place any declarations inside of the declaration block. `color: white;` is one declaration, with `color` being the property and `white` being the value, and `background-color: black;` is another declaration. diff --git a/foundations/html_css/flexbox/flexbox-intro.md b/foundations/html_css/flexbox/flexbox-intro.md index 2e2f7a483c1..e4add2b7ac1 100644 --- a/foundations/html_css/flexbox/flexbox-intro.md +++ b/foundations/html_css/flexbox/flexbox-intro.md @@ -86,5 +86,5 @@ The following questions are an opportunity to reflect on key topics in this less This section contains helpful links to related content. It isn't required, so consider it supplemental. - Interneting Is Hard has a tutorial on [modern CSS layouts with flexbox](https://internetingishard.netlify.app/html-and-css/flexbox/index.html). - +- Slaying the dragon tutorial on [Flexbox in 8 minutes](https://youtu.be/phWxA89Dy94?si=UOXlsTa0BMfQYG3q). - For a more interactive explanation and example, try this [Scrim on Flexbox](https://scrimba.com/learn/flexbox/your-first-flexbox-layout-flexbox-tutorial-canLGCw). Note that this Scrim requires logging into Scrimba in order to view. diff --git a/foundations/html_css/flexbox/project-landing-page.md b/foundations/html_css/flexbox/project-landing-page.md index 7435dd04e79..28e709058e5 100644 --- a/foundations/html_css/flexbox/project-landing-page.md +++ b/foundations/html_css/flexbox/project-landing-page.md @@ -4,11 +4,11 @@ For this project you'll be creating an entire web page from a design we'll provi The design we're providing you comes in the form of 2 images: one is an image of the complete website, and one has some details about some of the fonts and colors we've used. -Do _not_ be afraid to use google or go back to previous lessons to look something up. **In real life, professional developers use google _constantly_ for things that they have been doing for years.** At this point it is not expected that you will have everything memorized, so don't worry about it. Additionally, there are a few small details that you may not have encountered in our lessons yet. _This is by design._ These details are minor, and easily searched (e.g. google `css rounded corners`). +Do *not* be afraid to use google or go back to previous lessons to look something up. **In real life, professional developers use google *constantly* for things that they have been doing for years.** At this point it is not expected that you will have everything memorized, so don't worry about it. Additionally, there are a few small details that you may not have encountered in our lessons yet. *This is by design.* These details are minor, and easily searched (e.g. google `css rounded corners`). Get your project as close as you can to the design, but do not worry about getting it pixel-perfect. Don't get out your ruler or count pixels to find the exact margins between the various sections. The point of this assignment is to create something from scratch and get the various elements in more or less the right position relative to the rest. It doesn't matter if you use `margin: 24px` when the design actually has `margin: 48px`. -_Finally_, feel free to substitute your own content into this design. The images have some meaningless dummy content, but if you want to make up a business and personalize this page, please feel free to do so! Insert actual images in the placeholders, and feel free to play with the colors and fonts a bit too. +*Finally*, feel free to substitute your own content into this design. The images have some meaningless dummy content, but if you want to make up a business and personalize this page, please feel free to do so! Insert actual images in the placeholders, and feel free to play with the colors and fonts a bit too.
@@ -37,21 +37,23 @@ We know it may be tempting to look at the solutions when you get stuck or don't Once you have completed your project, feel free to look at the other solutions to see alternative ways the project was completed. -**DO NOT PEEK. Come ask for help in our [Discord server!](https://discord.com/channels/505093832157691914/516751477306294273) _(You need to [join the Discord server](https://discord.gg/fbFCkYabZB) first in order to see the channel)._** +**DO NOT PEEK. Come ask for help in our [Discord server!](https://discord.com/channels/505093832157691914/516751477306294273) *(You need to [join the Discord server](https://discord.gg/fbFCkYabZB) first in order to see the channel).*** ### Assignment
-Don't forget to commit early & often! You can [reference the Commit Message lesson here](https://www.theodinproject.com/paths/foundations/courses/foundations/lessons/commit-messages)! + +Don't forget to commit early & often! You can [reference the Commit Message lesson](https://www.theodinproject.com/paths/foundations/courses/foundations/lessons/commit-messages)! 1. Download the design images and take a look at what you're going to be creating here. [Image One (Full Design)](https://cdn.statically.io/gh/TheOdinProject/curriculum/81a5d553f4073e593d23a6ab00d50eef8620796d/foundations/html_css/project/imgs/01.png), [Image Two (Color and Fonts)](https://cdn.statically.io/gh/TheOdinProject/curriculum/81a5d553f4073e593d23a6ab00d50eef8620796d/foundations/html_css/project/imgs/02.png) - 1. The font that's being used in the images is roboto. - 2. Hero text is the statement that appears at the top of a web page. -2. There are many ways to tackle a project like this, and it can be overwhelming to look at a blank HTML document and not know where to start. Our suggestion: take it one section at a time. The website you're creating has 4 main sections (and a footer), so pick one and get it into pretty good shape before moving on. Starting at the top is always a solid plan. -3. For the section you're working on, begin by getting all the content onto the page before beginning to style it. In other words, do the HTML and _then_ do the CSS. You'll probably have to go back to the HTML once you start styling, but bouncing back and forth from the beginning will take more time and may cause more frustration. (Note: you don't need to use more than one stylesheet. Using only one CSS file is adequate for this project). -4. Many of the elements on this page are very similar to things you saw in our flexbox exercises... feel free to go back to those if you need a refresher. -5. Do not worry about making your project look nice on a mobile device. We'll learn that later. -6. When you finish, don't forget to push it up to GitHub! + 1. The font that's being used in the images is `Roboto`. + 1. Hero text is the statement that appears at the top of a web page. +1. There are many ways to tackle a project like this, and it can be overwhelming to look at a blank HTML document and not know where to start. Our suggestion: take it one section at a time. The website you're creating has 4 main sections (and a footer), so pick one and get it into pretty good shape before moving on. Starting at the top is always a solid plan. +1. For the section you're working on, begin by getting all the content onto the page before beginning to style it. In other words, do the HTML and *then* do the CSS. You'll probably have to go back to the HTML once you start styling, but bouncing back and forth from the beginning will take more time and may cause more frustration. (Note: you don't need to use more than one stylesheet. Using only one CSS file is adequate for this project). +1. Many of the elements on this page are very similar to things you saw in our flexbox exercises... feel free to go back to those if you need a refresher. +1. Do not worry about making your project look nice on a mobile device. We'll learn that later. +1. When you finish, don't forget to push it up to GitHub! +
### Viewing your project on the web @@ -66,5 +68,5 @@ There are a couple of ways to go about publishing your project, but the simplest - Go to your GitHub repo on the web and click the **Settings** button as shown in the screenshot below. ![Screenshot pointing to the Settings located in an example repository](https://cdn.statically.io/gh/TheOdinProject/curriculum/81a5d553f4073e593d23a6ab00d50eef8620796d/foundations/html_css/project/imgs/03.png) - Click on **Pages** on the left side bar. -- Change the **Branch** from _none_ to _main branch_ and click Save. +- Change the **Branch** from `None` to `main` and click Save. - It may take a few minutes (the GitHub website says up to 10), but your project should be accessible over the web from `your-github-username.github.io/your-github-repo-name` (obviously substituting your own details in the link). diff --git a/foundations/html_css/html-foundations/elements-and-tags.md b/foundations/html_css/html-foundations/elements-and-tags.md index f1f58f60028..6a09a7d53ad 100644 --- a/foundations/html_css/html-foundations/elements-and-tags.md +++ b/foundations/html_css/html-foundations/elements-and-tags.md @@ -6,7 +6,7 @@ HTML (HyperText Markup Language) defines the structure and content of webpages. This section contains a general overview of topics that you will learn in this lesson. -- Explain what HTML Tags are. +- Explain what HTML tags are. - Explain what HTML elements are. ### Elements and tags @@ -60,4 +60,4 @@ The following questions are an opportunity to reflect on key topics in this less This section contains helpful links to related content. It isn't required, so consider it supplemental. -- [Don't Fear the Internet's video about HTML](http://www.dontfeartheinternet.com/02-html) +- [Don't Fear the Internet's video about HTML](https://player.vimeo.com/video/24549728) diff --git a/foundations/html_css/html-foundations/html-boilerplate.md b/foundations/html_css/html-foundations/html-boilerplate.md index 197a0a65c16..551848cf532 100644 --- a/foundations/html_css/html-foundations/html-boilerplate.md +++ b/foundations/html_css/html-foundations/html-boilerplate.md @@ -114,8 +114,13 @@ To complete the boilerplate, add a `` element to the `index.html` file. Th The HTML boilerplate in the `index.html` file is complete at this point, but how do you view it in the browser? There are a couple of different options: -> A note: -> In order to avoid branching our lesson's instructions to accommodate for all of the differences between browsers, we are going to be using Google Chrome as our primary browser for the remainder of this course. All references to the browser will pertain specifically to Google Chrome. We **strongly** suggest that you use Google Chrome for all of your testing going forward. +
+ +#### Use Google Chrome + +In order to avoid branching our lesson's instructions to accommodate for all of the differences between browsers, we are going to be using Google Chrome as our primary browser for the remainder of this course. All references to the browser will pertain specifically to Google Chrome. We **strongly** suggest that you use Google Chrome for all of your testing going forward. + +
1. You can drag and drop an HTML file from your text editor into the address bar of your browser. @@ -168,7 +173,7 @@ It's still good to know how to write the boilerplate yourself in case you find y 1. Build some muscle memory by deleting the contents of the `index.html` file and trying to write out all the boilerplate again from memory. Don't worry if you have to peek at the lesson content the first few times if you get stuck. Just keep going until you can do it a couple of times from memory. -1. Run your boilerplate through the W3 [HTML validator](https://validator.w3.org/). Validators ensure your markup is correct and are an excellent learning tool, as they provide feedback on syntax errors you may be making often and aren't aware of, such as missing closing tags and extra spaces in your HTML. +1. Run your boilerplate through the W3 [HTML validator](https://validator.w3.org/#validate_by_input). Validators ensure your markup is correct and are an excellent learning tool, as they provide feedback on syntax errors you may be making often and aren't aware of, such as missing closing tags and extra spaces in your HTML.
diff --git a/foundations/html_css/html-foundations/links-and-images.md b/foundations/html_css/html-foundations/links-and-images.md index 452406a7e1d..1d0cabc60a0 100644 --- a/foundations/html_css/html-foundations/links-and-images.md +++ b/foundations/html_css/html-foundations/links-and-images.md @@ -62,7 +62,9 @@ While `href` specifies the destination link, `target` specifies where the linked You may have noticed that we snuck in the `rel` attribute above. This attribute is used to describe the relation between the current page and the linked document. -The `noopener` value prevents the opened link from gaining access to the webpage from which it was opened. The `noreferrer` value prevents the opened link from knowing which webpage or resource has a link (or 'reference') to it. It also includes the `noopener` behaviour and thus can be used by itself as well. +The `noopener` value prevents the opened link from gaining access to the webpage from which it was opened. + +The `noreferrer` value prevents the opened link from knowing which webpage or resource has a link (or 'reference') to it. The `noreferrer` value also includes the `noopener` behaviour and thus can be used by itself as well. Why do we need this added behaviour for opening links in new tabs? Security reasons. The prevention of access that is caused by `noopener` prevents [phishing attacks](https://www.ibm.com/topics/phishing) where the opened link may change the original webpage to a different one to trick users. This is referred to as [tabnabbing](https://owasp.org/www-community/attacks/Reverse_Tabnabbing). Adding the `noreferrer` value can be done if you wish to not let the opened link know that your webpage links to it. @@ -156,7 +158,7 @@ Think of your domain name (`town.com`) as a town, the directory in which your we Websites would be fairly boring if they could only display text. Luckily HTML provides a wide variety of elements for displaying all sorts of different media. The most widely used of these is the image element. -To display an image in HTML we use the `` element. Unlike the other elements we have encountered, the `` element is self-closing. Empty, self-closing HTML elements do not need a closing tag. +To display an image in HTML we use the `` element. Unlike the other elements we have encountered, the `` element is a void element. As we have seen earlier in the course, void elements do not need a closing tag because they are naturally empty and do not contain any content. Instead of wrapping content with an opening and closing tag, it embeds an image into the page using a src attribute which tells the browser where the image file is located. The src attribute works much like the href attribute for anchor tags. It can embed an image using both absolute and relative paths. @@ -172,7 +174,7 @@ For example, using an absolute path we can display an image located on The Odin -To use images that we have on our own websites, we can use a relative path. +To display images on your website that are hosted on your own web server, you can use a relative path.
@@ -322,3 +324,4 @@ This section contains helpful links to related content. It isn't required, so co - [Interneting is hard's treatment on HTML links and images](https://internetingishard.netlify.app/html-and-css/links-and-images) - [What happened the day Google decided links including (`/`) were malware](https://www.itpro.co.uk/609724/google-apologises-after-blacklisting-entire-internet) - [Chris Coyier's When to use target="_blank" on CSS-Tricks](https://css-tricks.com/use-target_blank/) +- If you're looking to deepen your understanding of the various image formats used on the web, [the following article which is titled: Which is the Best Image Format for Your Website?](https://imagekit.io/blog/best-image-format-for-web/) from imagekit.io is a great resource. It offers a detailed comparison of JPEG, PNG, GIF, and WebP formats, helping you choose the right one for your needs. Note that the article doesn't cover SVG, but it's still an excellent guide for the other common formats. diff --git a/foundations/html_css/html-foundations/lists.md b/foundations/html_css/html-foundations/lists.md index bae11bc8fdb..d5a218384de 100644 --- a/foundations/html_css/html-foundations/lists.md +++ b/foundations/html_css/html-foundations/lists.md @@ -20,10 +20,13 @@ Unordered lists are created using the `
+ Ubuntu/Windows Dual-Boot + ### Read this entire section before starting @@ -286,7 +301,9 @@ If you encounter an error requesting you to disable **Intel RST** while attempti
+ ChromeOS/ChromeOS Flex + With the recent addition of being able to run a Linux terminal, the ChromeOS platform has been opened up to the ability to install native Linux applications. If you wish to use your Chromebook to complete The Odin Project, you will need to ensure you meet a couple requirements: @@ -301,6 +318,7 @@ Once you have successfully met both of these requirements, you should be able to
+ WSL2 (Advanced) Using WSL2 is an quick and easy way to get started with using Linux, allowing you to run a Linux distribution from within Windows. WSL2 is available on Windows 10 version 2004 and higher (Build 19041 and higher) and Windows 11. @@ -308,8 +326,11 @@ Using WSL2 is an quick and easy way to get started with using Linux, allowing yo To make it clear: you are going to be using a different OS, this is not a way to avoid using Linux. Due to how WSL2 is integrated with Windows it often causes significant confusion to new learners. Use the Virtual Machine if you want a clear separation between your Windows and Linux so the curriculum is easier to follow.
+ #### WSL2 and Linux instructions + Because WSL2 is a full-fledged Linux distribution, almost everything that the curriculum teaches about Linux is also applicable to WSL2. In future lessons, whenever there are instructions that differ by OS, you should follow the Linux instructions, unless the lesson includes WSL2-specific instructions. +
### Step 1: Installations @@ -352,12 +373,17 @@ On Windows there are three primary ways to open WSL2. - If you search for Ubuntu in the application search bar you should see a application titled Ubuntu; open it to start a new terminal session.
+ You might notice when you open WSL2 via Windows Terminal, you'll see a window with a different color scheme and a different icon compared to opening a terminal through Ubuntu in your applications. This is because Windows Terminal comes with a default color scheme for Ubuntu meant to emulate how a real Ubuntu terminal looks. This difference is purely cosmetic, and there is no practical difference between the two. +
+ When opening your WSL2 terminal ensure that you do not see `/mnt/c` at the start of the line. `/mnt/c` is where your Windows installation lives when working within WSL2, and messing around there can have unintended consequences. +
+
### Google Chrome installation @@ -370,6 +396,7 @@ Look at this [usage share of web browsers](https://en.wikipedia.org/wiki/Usage_s Choose your Operating System:
+ Linux #### Step 1: Download Google Chrome @@ -382,17 +409,20 @@ wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb ```
-### Copy and paste keyboard shortcuts -You have probably noticed that the common keyboard shortcut: Ctrl + V to paste something doesn't work in the terminal. In order to paste your text input into your terminal you can use: Ctrl + Shift + V keyboard shortcut combination, instead. It is also very handy to know that the: Ctrl + Shift + C keyboard combination will copy any highlighted text from your terminal, which can then be pasted later. + +#### Copy and paste keyboard shortcuts + +You have probably noticed that the common keyboard shortcut: Ctrl + V to paste something doesn't work in the terminal. In order to paste your text input into your terminal you can use: Ctrl + Shift + V keyboard shortcut combination, instead. It is also very handy to know that the: Ctrl + Shift + C keyboard combination will copy any highlighted text from your terminal, which can then be pasted later. +
#### Step 2: Install Google Chrome - Enter the following command in your terminal to install **Google Chrome** `.deb` package - ```bash - sudo apt install ./google-chrome-stable_current_amd64.deb - ``` + ```bash + sudo apt install ./google-chrome-stable_current_amd64.deb + ``` - Enter your password, if needed @@ -400,11 +430,12 @@ You have probably noticed that the common keyboard shortcut: Ctrl + < #### A note on typing passwords in the terminal - When using a command in the terminal that requires you to enter your password for authentication (such as sudo), you will notice that the characters aren't visible as you type them. While it might seem like the terminal isn’t responding, don’t worry! +When using a command in the terminal that requires you to enter your password for authentication (such as sudo), you will notice that the characters aren't visible as you type them. While it might seem like the terminal isn’t responding, don’t worry! + +This is a security feature to protect confidential information, like how password fields on websites use asterisks or dots. By not displaying the characters you write, the terminal keeps your password secure. - This is a security feature to protect confidential information, like how password fields on websites use asterisks or dots. By not displaying the characters you write, the terminal keeps your password secure. +You can still enter your password as normal and press Enter to submit it. - You can still enter your password as normal and press Enter to submit it.
@@ -439,6 +470,7 @@ Chrome is going to use this terminal to output various messages and won't let yo
+ MacOS #### Step 1: Download Google Chrome @@ -467,6 +499,7 @@ Chrome is going to use this terminal to output various messages and won't let yo
+ WSL2 #### Step 1: Download Google Chrome @@ -502,4 +535,4 @@ The following questions are an opportunity to reflect on key topics in this less This section contains helpful links to related content. It isn't required, so consider it supplemental. -- It looks like this lesson doesn't have any additional resources yet. Help us expand this section by contributing to our curriculum. +- Google Chrome is one of the most important tools that you will be using throughout the curriculum. This reference has many [common shortcuts that you may find useful when using Chrome](https://support.google.com/chrome/answer/157179?hl=en&co=GENIE.Platform%3DDesktop#zippy=%2Ctab-window-shortcuts). diff --git a/foundations/introduction/how_this_course_will_work.md b/foundations/introduction/how_this_course_will_work.md index 795859ab9a6..5342b8ac95c 100644 --- a/foundations/introduction/how_this_course_will_work.md +++ b/foundations/introduction/how_this_course_will_work.md @@ -12,13 +12,20 @@ By the end of this unit, you should not only understand how the web works but al This section intentionally covers a very broad range of topics. It's silly to go diving straight into server-side programming without having a context for what it is and why it's useful (and why you should learn it!). +### Lesson overview + +This section contains a general overview of topics that you will learn in this lesson. + +- Understand how The Odin Project's curriculum works. +- Understand how the Foundations course works. + ### How it works This curriculum works by aggregating the best content from across the internet to teach a specific topic. In each lesson, we'll introduce the topic and try to provide some useful context before pointing you to external resources made by others. Most lessons will contain questions that you should be able to answer before moving on. Some lessons will include exercises for you to complete. In addition, we provide several projects throughout the curriculum to help you grow your understanding by actually building things. -Try not to think of The Odin Project, or programming, as a class in school. It's not material you learn all at once to take a test, and then pass or fail. You can think of it as a snowball. You, yourself, are a snowball. You're rolling down a hill full of snow; the further you roll, the more snow will stick to you. Sure, snow will also fall off you, and you'll forget things often, but that's just part of the process. Don't worry if you reach a project and feel like you haven't retained or memorized anything. That's natural and happens to everyone. The information will come back to you as you start solving your problems one at a time, relying on Google and the Odin Community for help. +Try not to think of The Odin Project, or programming, as a class in school. It's not material you learn all at once to take a test, and then pass or fail. You can think of it as a snowball. You, yourself, are a snowball. You're rolling down a hill full of snow; the further you roll, the more snow will stick to you. Sure, snow will also fall off you, and you'll forget things often, but that's just part of the process. Don't worry if you reach a project and feel like you haven't retained or memorized anything. That's natural and happens to everyone. **The projects are not tests of what you have memorized so far.** They are practice points where the information will come back to you as you start solving your problems one at a time, relying on Google and the Odin Community for help. ### A note about tools @@ -29,7 +36,7 @@ The truth is that once you complete this curriculum, you will **not need** a cou One of the most difficult parts about this course is adopting the right mindset. An even bigger challenge is learning the core ideas of programming. It isn't just about coding, it is about problem-solving, asking the right questions, and doing enough research. Getting into a position where you are comfortable with the skills will mean that you will also be comfortable at expanding your skill-set. Once you have a solid *base*, it will be simpler to expand upon it. This is exactly what The Odin Project is about: developing these *skills*. After completing the course you will be in a position where you can simply jump straight into the documentation for anything you are trying to learn. -Reading the documentation is the best way to learn any tooling. But it takes skill to master. Many people feel intimidated by the technical jargon, which is understandable. People who write documentations usually assume a background in programming. This is exactly why we give you plenty of material to read on your own. +Reading the documentation is the best way to learn any tooling. But it takes skill to master. Many people feel intimidated by the technical jargon, which is understandable. People who write documentation usually assume a background in programming. This is exactly why we give you plenty of material to read on your own. The skills you will gain from completing The Odin Project will be the foundation that you will be building upon for years and decades to come. If you come out of the course thinking that you need another course like this one to learn something like Python, then you either don't believe in yourself or you haven't taken away the important ideas that are covered in this course. @@ -68,6 +75,13 @@ Additional resources are the only thing that is considered optional unless expli +### Knowledge check + +The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. + +- [What is The Odin Project?](#introduction) +- [Should you skip anything in The Odin Project or complete it non-linearly?](#what-comes-next) + ### Additional resources This section contains helpful links to related content. It isn't required, so consider it supplemental. diff --git a/foundations/introduction/introduction_to_web_development.md b/foundations/introduction/introduction_to_web_development.md index f0b262525a8..364415eac6e 100644 --- a/foundations/introduction/introduction_to_web_development.md +++ b/foundations/introduction/introduction_to_web_development.md @@ -55,7 +55,7 @@ The web development industry has a long history of successful developers with va ### Why Odin? -I want you to know that this will not be easy. +We want you to know that this will not be easy. There are plenty of other online curriculums for beginners, but they are often taught in an extremely isolated and controlled environment and cover only a specific topic. diff --git a/foundations/introduction/join_the_odin_community.md b/foundations/introduction/join_the_odin_community.md index c4c1b6aeccc..578930b0e42 100644 --- a/foundations/introduction/join_the_odin_community.md +++ b/foundations/introduction/join_the_odin_community.md @@ -1,6 +1,14 @@ ### Introduction -Working and collaborating with other people is an important part of working as a web developer. Therefore, we at The Odin Project encourage you to participate in our online chat community, which we'll talk more about below. By joining the community, you can grow alongside other Odinites and help each other learn web development. While you're at it, you can check out our [Facebook page](https://www.facebook.com/theodinproject/), [follow us on X](https://x.com/TheOdinProject) and catch up on [Instagram](https://www.instagram.com/theodinproject/). Use #TheOdinProject to share your Odin Project progress, updates, thoughts and to see what other Odin students are up to! +Working and collaborating with other people is an important part of working as a web developer. Therefore, we at The Odin Project encourage you to participate in our online chat community, which we'll talk more about below. By joining the community, you can grow alongside other Odinites and help each other learn web development. While you're at it, you can check out [our Facebook page](https://www.facebook.com/theodinproject/), [follow us on X](https://x.com/TheOdinProject) and catch up on [our Instagram page](https://www.instagram.com/theodinproject/). Use #TheOdinProject to share your Odin Project progress, updates, thoughts and to see what other Odin students are up to! + +### Lesson overview + +This section contains a general overview of topics that you will learn in this lesson. + +- Learn about The Odin's community and how to join it. +- Explain how to ask good and detailed questions. +- Explain good practices for helping others with their questions. ### Why a community is awesome for you @@ -56,7 +64,7 @@ In the chat rooms, code can be displayed differently from normal sentences by us \`Your Code\` -**For multiple lines of code:** use three backticks _on a separate line_ above and below your code. +**For multiple lines of code:** use three backticks *on a separate line* above and below your code. \`\`\` @@ -64,9 +72,9 @@ Your Multiple Lines of Code \`\`\` -You can also use _code highlighting_ to add color to your multi-line code by specifying the language: +You can also use *code highlighting* to add color to your multi-line code by specifying the language: -\`\`\`**js** or **javascript** +\`\`\`**js** or **JavaScript** Your Multiple Lines of Colorful Code @@ -83,45 +91,45 @@ Your Multiple Lines of Colorful Code Not only is it important to know how to ask an effective question, but it is also important to know how to help others effectively. Please take a moment to review these guidelines so that you will have proper expectations of the help you will receive in our Discord community. In addition, come back and review these guidelines when you are ready to start helping others. -#### 1. Instead of answering the question, guide them to the answer. +#### 1. Instead of answering the question, guide them to the answer Unless the problem is a simple typo or syntax error, it is more beneficial to guide them to find their own answer. This approach will teach good debugging skills and will increase their ability to solve future problems. Start by asking probing questions, such as "What have you already tried?", “What do you expect this function to do?”, or “What do you think that error means?”. -#### 2. Help only when you are certain of the answer. +#### 2. Help only when you are certain of the answer If you are not 100% certain of the answer, you may end up doing more harm than good, so please let someone else answer it. Do not worry about how long someone has to wait for an answer. The right answer is worth the wait. -#### 3. Help only when no one else is currently helping. +#### 3. Help only when no one else is currently helping If somebody is already getting help, do not jump in the middle of the conversation. We know you mean well, but it is overwhelming for the person receiving help to follow multiple conversations. -#### 4. Help only when you have plenty of time. +#### 4. Help only when you have plenty of time If you do not have much time to help, please let someone else answer the question. -#### 5. Adjust your expectations to their level. +#### 5. Adjust your expectations to their level If the question does not reveal where they are in the curriculum, ask them so that you can adjust your expectations to their knowledge level. -#### 6. Ask for clarifications. +#### 6. Ask for clarifications If the question seems confusing or ambiguous, ask for more clarity, or politely link them to our bot command `/question`, which links to the [How to be great at asking coding questions](https://medium.com/@gordon_zhu/how-to-be-great-at-asking-questions-e37be04d0603) article. -#### 7. Ask for live code. +#### 7. Ask for live code If the question needs to have live code to fully understand or debug, ask them to use [replit](https://replit.com) to provide it. If the problem is difficult to isolate, they should recreate the problem with isolated code. -#### 8. Do not answer googleable questions. +#### 8. Do not answer googleable questions Learning how to research these questions is a very important skill for developers, so we need to empower them to find their own answer. When we answer these questions, it hinders their personal growth and makes them codependent on our community. -Instead of answering these questions, politely ask them to google their question or use our bot command `/google` with the search terms. +Instead of answering these questions, politely ask them to google their question or use our bot command `/search google` with the search terms. -#### 9. Do not answer questions covered in our curriculum. +#### 9. Do not answer questions covered in our curriculum If you know that the answer is provided in our curriculum, ask them where they are at in the curriculum. @@ -129,48 +137,47 @@ If they have not reached that portion of the curriculum, let them know they will If they have already been through that portion of the curriculum, politely direct them to review that lesson. -#### 10. Answer the question before pointing out other problems. +#### 10. Answer the question before pointing out other problems When helping someone it can be easy to spot other problems in their code. Resolve the original question, before pointing out any other problems that need attention. -#### 11. Encourage students to use a debugger. +#### 11. Encourage students to use a debugger It is common for students to not understand the importance of using a debugger to look at the values of their variables at different points in their program. When students are getting unexpected values, politely encourage them to use a debugger with our bot command `/debug`. -#### 12. Watch for students that need to take a step back. +#### 12. Watch for students that need to take a step back It is common for students to focus too hard on a problem and not be able to clearly see everything. When this situation arises, politely encourage them to step back from the problem and take a break. Oftentimes, stepping away from a problem will help them see the bigger picture and how to solve it. -#### 13. Watch for students that are in over their head. +#### 13. Watch for students that are in over their head It is common for students to skip a lesson/project or think they know more than they actually do. When this situation arises, politely encourage them to go back and reread a section of the curriculum for more understanding. -#### 14. Admit when the problem goes beyond your current knowledge. +#### 14. Admit when the problem goes beyond your current knowledge It is common for the actual issue to go beyond the initial question. If it goes beyond your current knowledge, it is important to admit that you are unsure of the correct answer and let someone else help. After digging deeper into the problem, they might be able to continue troubleshooting on their own or they can wait for someone more experienced to help. -#### 15. Be patient. +#### 15. Be patient Helping others solve a problem is not always easy. Remember to be patient as they struggle through the problem. -#### 16. Duck out of the conversation if you get frustrated. +#### 16. Duck out of the conversation if you get frustrated Sometimes there are misunderstandings and interactions go poorly. You are a volunteer and are not obligated to help when things get out of hand. Politely duck out of the conversation and let someone else step up. - ### Assignment
-1. First, create a free [GitHub account](https://github.com/join). As you will discover, GitHub is an integral part of the development workflow. +1. First, [create a free GitHub account](https://github.com/join). As you will discover, GitHub is an integral part of the development workflow. -2. Now, sign in to our [Discord server](https://discord.gg/theodinproject). Pop in and say hello! We've created an introductions room which is a great place to introduce yourself and we're always happy to welcome new community members. We have chat rooms for every development topic covered in our curriculum. Log into the chat and start exploring! +1. Now, sign in to [our Discord server](https://discord.gg/fbFCkYabZB). Pop in and say hello! We've created an introductions room which is a great place to introduce yourself and we're always happy to welcome new community members. We have chat rooms for every development topic covered in our curriculum. Log into the chat and start exploring! - **Link your GitHub to your Discord profile:** Go to `Discord Settings > Connections`, then click the GitHub icon. In the new tab that opens click "Allow Access", then back in Discord make sure "Display on profile" is toggled on. This will allow others to see what you're working on and vice versa! -3. Here are some guidelines before you dive in: +1. Here are some guidelines before you dive in: - **Read the rules and FAQ:** Please take the time to read and understand our rules and FAQ. On the left sidebar in Discord, navigate to `TOP META`-> `rules` and `faq`. - **Remember the human:** Behind every username there is a person with feelings! Be kind! If you don't have anything nice to say, don't say anything at all. @@ -182,8 +189,16 @@ Sometimes there are misunderstandings and interactions go poorly. You are a volu
+### Knowledge check + +The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. + +- [How do you join The Odin Project's Discord server?](https://discord.gg/fbFCkYabZB) +- [What makes a good question that's easier for others to help with?](#asking-for-help) +- [How can you more effectively help others with their coding problems?](#how-to-help-others-solve-coding-problems) + ### Additional resources -This section contains helpful links to related content. It isn’t required, so consider it supplemental. +This section contains helpful links to related content. It isn't required, so consider it supplemental. - For more information on formatting, check out [Discord Markdown 101](https://support.discord.com/hc/en-us/articles/210298617-Markdown-Text-101-Chat-Formatting-Bold-Italic-Underline-). diff --git a/foundations/introduction/motivation_and_mindset.md b/foundations/introduction/motivation_and_mindset.md index 9e1e2269550..221b3816c45 100644 --- a/foundations/introduction/motivation_and_mindset.md +++ b/foundations/introduction/motivation_and_mindset.md @@ -2,7 +2,7 @@ Learning to code is incredibly rewarding but can also be difficult and frustrating. Like any skill worth knowing, it takes time to acquire, and it can't be learned in a weekend or even a month. With that said, we believe anyone can learn how to program as long as they are willing to put in the time and effort. -So before we get into the meat of the curriculum, we're going to go over the following to help you get the most out of The Odin Project: the things that will help you succeed in your goal of learning to code and the pitfalls that you should try to avoid. +So before we get into the meat of the curriculum, we'll cover the following aspects to help you get the most out of The Odin Project: factors that will help you succeed in learning to code and the pitfalls that you should try to avoid. ### Motivation @@ -54,7 +54,7 @@ You will inevitably get stuck at some point in the curriculum, perhaps due to a - Take a break: Allow your diffuse learning state to work on the problem. - Ask for help in the [TOP Discord server](https://discord.gg/theodinproject); come prepared with your research. People will be more willing to help you when they can see you have already put effort into trying to figure out the solution on your own. -Additionally, feel free to follow the diagram below that should help you going through problems that you may come across: +Additionally, feel free to follow the diagram below to help you navigate problems that you may come across: ![diagram to help learners go through problems when they are stuck](https://cdn.statically.io/gh/TheOdinProject/curriculum/978ba0e91a6a47452de819246f4c495e6b092f54/foundations/introduction/motivation_and_mindset/imgs/00.png) @@ -64,13 +64,13 @@ As technology advances, we have seen some incredible tools emerge that can help While these tools are amazing, learners should be aware of the impacts that using such tools can have on core competency. David Humphrey, a computer science professor, [wrote about ChatGPT and its potentially negative impacts on core learning.](https://blog.humphd.org/cheatgpt/) It is a good read about the pitfalls of using generative AI in an educational context. -For learners that are new to programming, tools like ChatGPT or Github Copilot can result in some blindspots and gaps in your knowledge. +For learners who are new to programming, tools like ChatGPT or GitHub Copilot can result in blindspots and gaps in your knowledge. 1. By using a generative AI, learners may miss the opportunity to discover how something works and why things are done that way. -1. Asking good questions is an important skill to have, and using generative AI to skip asking people (like our helpful Discord community) means that your development of this skill is delayed. +1. Asking good questions is an important skill, and relying on generative AI instead of asking people (like our helpful Discord community) can delay the development of this skill. 1. Learning to talk about the code that one writes is another important skill. In a professional environment, it is highly likely that you will be doing code reviews where you have to explain the how and why behind what you are presenting. Using the Odin community to ask good questions about your code when you require help can help develop this skill as well. 1. As David Humphrey mentions, the output of generative AI must be closely scrutinized, and learners who are new to programming generally don't have a good overall understanding to be able to determine if the output is good or bad. -1. While learning how to provide good prompts to an AI tool is a skill, it is one that is supplementary to developing foundational programming skills. The Odin curriculum strives to teach that foundational skill. +1. While learning how to provide good prompts to an AI tool is a skill, it is supplementary to developing foundational programming skills. The Odin curriculum strives to teach that foundational skill. 1. AI tools are designed to answer questions and are not designed to help learners develop research and problem solving skills. If you ask an AI for information, it will provide information to you. If you ask a human, they may invite you to share your understanding of the problem and offer some guidance on how to discover a solution. 1. Without practice in research, problem solving and critical thinking, interviews could be a struggle since it is very likely that applicants would not be allowed to use AI tools. @@ -80,11 +80,11 @@ We do not recommend using AI tools for your learning. You will have more success with Odin by putting **consistent** time into it rather than working on it once a week. Building a habit of studying every day at a specific time and with a specific goal will ensure that you make consistent progress. -It may take you longer than others to grasp concepts, or it may take you less time. This doesn't mean you're smarter or dumber than others, it means you've had differing life experiences that may or may not have prepared you for learning this stuff. Someone who grew up around an engineer may have some advantages over someone who didn't, but it doesn't mean you can't learn those skills. +It may take you longer than others to grasp concepts, or it may take you less time. This doesn't mean you're smarter or dumber than others, it means you've had differing life experiences that may or may not have prepared you for learning those concepts. Someone who grew up around an engineer may have some advantages over someone who didn't, but it doesn't mean you can't learn those skills. -The Odin Project isn't like college or university, it is self paced and allows you to get a really solid grasp of concepts before moving on. In school, you're forced to keep up or you will fail. The difference here is that coming into The Odin Project, you're not expected to have much knowledge; there are no prerequisites. We've had people be successful coming through here who only knew how to check their email with a computer. We've also seen success from computer science degree holders. Treating The Odin Project like a static timeline is understandable, but is a sign of misplaced expectations. You don't know what you don't know yet, and that's OK! There are no due-dates on things in The Odin Project so you can spend the time to do it right and discuss the topics. +The Odin Project isn't like college or university, it is self-paced and allows you to get a solid grasp of concepts before moving on. In school, you're forced to keep up, or you will fail. The difference with The Odin Project is that you’re not expected to have much prior knowledge; there are no prerequisites. We've had people be successful coming through here who only knew how to check their email with a computer. We've also seen success from computer science degree holders. Treating The Odin Project like a static timeline is understandable, but is a sign of misplaced expectations. You don't know what you don't know yet, and that's OK! There are no due-dates on lessons in The Odin Project, so you can spend enough time to do it right and discuss the topics. -Deadlines cause un-needed stress. Since The Odin Project is a free and open platform, you are not beholden to a deadline. Creating your own deadlines is a good way to rush concepts that should not be rushed. This course is very research based, meaning you will have to do research to complete tasks and projects. There's no telling if you can find the article or post that helps you in the right way, quickly to meet your deadlines, but we bet you learned a TON along the way that you can use in the future. People that do this kind of research and strive to write better solutions tend to become better developers in the future. There's no knowing how long it could take you to learn how to query stuff to find your answers. There are no solid guidelines on that. If you're doing The Odin Project because you need a high paying job *right-now*, you're not going to become a solid developer within the timeframe you have set. Stress and anxiety absolutely do not help you learn either. Relax and just enjoy the ride. +Deadlines cause unneeded stress. Since The Odin Project is a free and open platform, you are not beholden to a deadline. Creating your own deadlines can lead to rushing through concepts that should not be rushed. This course is very research based, meaning you will have to do research to complete tasks and projects. There’s no guarantee you will find the right article or post quickly enough to meet your deadlines, but you will likely learn a TON along the way that you can use in the future. People that do this kind of research and strive to write better solutions tend to become better developers in the future. There’s no way to know how long it will take you to learn how to query concepts to find your answers. There are no solid guidelines on that. If you're doing The Odin Project because you need a high-paying job *right now*, you’re unlikely to become a solid developer within the timeframe you have set. Stress and anxiety absolutely do not help you learn either. Relax and just enjoy the ride. Long story short: Don't worry, just go learn! @@ -119,7 +119,7 @@ What to do during your break: - Play a quick game. - Go for a short walk outside. -Checkout this article for [more information on breaks & productivity](https://simpleprogrammer.com/taking-breaks-will-boost-productivity/). +Check out this article for [more information on breaks & productivity](https://simpleprogrammer.com/taking-breaks-will-boost-productivity/). #### Digital distractions @@ -131,13 +131,13 @@ Digital distractions are email and Facebook notifications and time-wasting websi Physical distractions are distractions from your environment, like a TV in the background or other people talking. These distractions can be just as damaging to your focus as digital distractions. -**Solution:** Find a quiet place to study where you can go to focus in your home. If that's not an option, you can use noise cancelling headphones to block out noisy distractions in your environment. There are also complimentary public and university libraries that are serene and comfortable. Some libraries even operate 24/7, uninterrupted. Beyond just providing a pleasant study space, the presence of others studying around you instills a sense of productivity. +**Solution:** Find a quiet place in your home where you can focus on your studies. If that's not an option, you can use noise cancelling headphones to block out noisy distractions in your environment. There are also complimentary public and university libraries that are serene and comfortable. Some libraries even operate 24/7, uninterrupted. Beyond just providing a pleasant study space, the presence of others studying around you instills a sense of productivity. #### Rabbit holes Because we cover so much material on The Odin Project and link to so many high quality courses and tools, it is easy for students to get pulled into rabbit holes by spending time trying to learn all there is to know about a subject that they aren't ready for or won't benefit them much. **We have put a lot of effort into structuring the curriculum** so that all of the important things that you need to know about web development are covered exactly when you need to know them. -**Solution:** Stick to the path laid out as much as possible. Try to limit time spent going down rabbit holes as these sidetracks can really ruin your momentum. +**Solution:** Stick to the path laid out as much as possible. Try to limit time spent going down rabbit holes, as these sidetracks can really ruin your momentum. #### Comparing yourself to others @@ -145,7 +145,7 @@ Students often compare themselves to others who are farther along in their codin **Solution:** Only compare yourself to your past self. Have your abilities and knowledge improved from where you were last week, last month, or last year? Be proud of the progress that you've made! -#### Counter productive note-taking +#### Counterproductive note-taking The Odin Project does not recommend taking a lot of notes throughout your web development educational journey because it can be time-consuming and often leads to wasted effort. @@ -153,7 +153,7 @@ The Odin Project does not recommend taking a lot of notes throughout your web de ### Conclusion -Learning any new skill is a journey full of speed bumps and obstacles to be overcome. We hope that the principles laid out here will put you in a much better position to succeed and get the most out of The Odin Project. +Learning any new skill is a journey full of speed bumps and obstacles to overcome. We hope that the principles laid out here will put you in a much better position to succeed and get the most out of The Odin Project. ### Assignment diff --git a/foundations/javascript_basics/clean_code.md b/foundations/javascript_basics/clean_code.md index a91bf9bb8b4..5576306d089 100644 --- a/foundations/javascript_basics/clean_code.md +++ b/foundations/javascript_basics/clean_code.md @@ -1,4 +1,3 @@ - ### Introduction You might think that the majority of a developer's work involves writing code. However, in reality, a significant amount of time is spent on *reading* code. This includes code written by other team members, code written by people who are no longer part of your team, and even code that you wrote two weeks ago but may not remember much about. @@ -24,11 +23,11 @@ Consider the following examples: Example A: ```javascript +const x= function (z){ + const w = "Hello "; +return w + z -const x = function (z) { - const w = "Hello "; -return w + z -}; + } x("John"); ``` @@ -44,13 +43,13 @@ const generateUserGreeting = function (name) { generateUserGreeting("John"); ``` -Which of these examples do you find easier to read? It's immediately clear that the latter one is more meaningful. Surprisingly, both of these functions perform the exact same task \(in the exact same way!\), and both are valid code. But the second one is much more readable. Why? +Which of these examples do you find easier to read? It's immediately clear that the latter one is more meaningful. Surprisingly, both of these functions perform the exact same task (in the exact same way!), and both are valid code. But the second one is much more readable. Why? -In the first example, single-letter variables are used and the indentation is inconsistent. The result is a piece of code that is confusing and messy. +In the first example, single-letter variables are used and the indentation and spacing are inconsistent. The result is a piece of code that is confusing and messy. Imagine you're collaborating on a project with someone who has written the first function. How long will it take you to decipher what's going on so you can continue with your work? Or perhaps you've written it yourself some time ago and completely forgotten that it even existed. In both situations, you will eventually understand what is happening, but it's not going to be fun. -Example B represents clean code. While you may not know what each part does, it's much easier to guess what's happening because the functions and variables are named clearly. The indentation follows a consistent and logical pattern. +Example B represents cleaner code. While you may not know what each part does, it's much easier to guess what's happening because the functions and variables are named clearly. The indentation and spacing follow a consistent and logical pattern. Single characters can be used as variable names in the context of a loop or a callback function, but avoid them elsewhere. @@ -58,7 +57,17 @@ Single characters can be used as variable names in the context of a loop or a ca camelCase is a naming convention that allows writing multiple words together without spaces or punctuation. In camelCase, when a variable name consists of multiple words like our `setTimeout` example, the first word is written completely in lowercase, while the first letter of the second word (and any subsequent words) are capitalized. -Throughout this lesson, most of our variables and functions (at least in the good examples!) will be named using camelCase. It's a good example to follow. +Throughout this lesson, most of our variables and functions will be named using camelCase. While not every language uses this convention, it's very common in JavaScript so it'll be a good example to follow. + +
+ +#### Conventions are only conventions + +While this lesson shares some examples on ways to clean up code, in reality, every organization will have different specific approaches, some of which may differ slightly from our examples in this lesson. Nothing is absolute. + +What matters most is that these approaches all serve the same overall purpose - improve code readability and maintainability. Until a time comes where you need to follow a specific set of conventions, it is sensible to follow some convention and be consistent with them. + +
### Naming functions and variables @@ -70,44 +79,46 @@ In our good example, we have a variable `greeting`, to which the parameter `name Now, try picturing a conversation with someone about the bad example. The function is named `x` with variables like `z`, and `w`. Oof, not nice. -#### Use a consistent vocabulary +#### Use consistent vocabulary -Variables of the same type should have consistent naming. Consider the following examples from a game: +Variables of the same type ideally follow a consistent naming system. Consider the following examples from a game: ```javascript - // Good +// Consistent naming function getPlayerScore(); function getPlayerName(); function getPlayerTag(); +``` -// Bad +They all follow the same naming system of "get a thing". Now consider the following: + +```javascript +// Inconsistent naming function getUserScore(); function fetchPlayerName(); function retrievePlayer1Tag(); ``` -In the bad example, three different names are used to refer to the player and the actions taken. Additionally, three different verbs are used to describe these actions. The good example maintains consistency in both variable naming and the verbs used. - -Variables should always begin with a noun or an adjective (that is, a noun phrase) and functions with a verb. +In the inconsistent example, three different verbs are used for the functions. While they all mean a similar thing, at a glance you might assume different verbs were used for a specific reason (e.g. "getting" might not be *quite* the same thing as "fetching" in some contexts). Additionally, what's the difference between `User`, `Player` and `Player1`? If there is no difference then ideally, you'd use the same name e.g. `Player`. Consistency allows for predictability. -Another set of examples can illustrate why this matters: +Variables should preferably begin with a noun or an adjective (that is, a noun phrase), as they typically represent "things", whether that thing is a string, a number etc. Functions represent actions so ideally begin with a verb. ```javascript -// Good +// Preferable const numberOfThings = 10; const myName = "Thor"; const selected = true; -// Bad (these start with verbs, could be confused for functions) +// Not preferable (these start with verbs, could be confused for functions) const getCount = 10; -const isSelected = true; +const showNorseGods = ["Odin", "Thor", "Loki"]; -// Good +// Preferable function getCount() { return numberOfThings; } -// Bad (it's a noun) +// Not preferable (myName doesn't represent some kind of action) function myName() { return "Thor"; } @@ -115,35 +126,35 @@ function myName() { ### Use searchable and immediately understandable names -Sometimes, it can be tempting to use an undeclared variable. Let's take another look at an example: +Sometimes, it can be tempting to use "magic values" i.e. explicit values, such as bare numbers or strings. Let's take another look at an example: ```javascript setTimeout(stopTimer, 3600000); ``` -The problem is obvious. What does the undeclared variable `3600000` mean, and how long is this timeout going to count down before executing `stopTimer`? Even if you know that JavaScript understands time in milliseconds, a calculator is needed. +The problem is obvious. What does the magic number `3600000` mean, and how long is this timeout going to count down before executing `stopTimer`? Even if you know that JavaScript understands time in milliseconds, you'd probably need a calculator or Google to figure out how many seconds or minutes it represents. Now, let's make this code more meaningful by introducing a descriptive variable: ```javascript -const MILLISECONDS_PER_HOUR = 60 * 60 * 1000; // 3,600,000; +const ONE_HOUR = 3600000; // Can even write as 60 * 60 * 1000; -setTimeout(stopTimer, MILLISECONDS_PER_HOUR); +setTimeout(stopTimer, ONE_HOUR); ``` Much better, isn't it? The variable is declared with a descriptive name, and you don't need to perform any calculations when reading this code. -You might wonder why this variable is declared with all caps when we recommended camelCase earlier. This is a convention to be used when the programmer is absolutely sure that the variable is *truly* a constant. We know that the milliseconds in an hour will never change, so it's appropriate here. +You might wonder why this variable is declared with all caps when we recommended camelCase earlier. This is a convention to be used when the programmer is absolutely sure that the variable is *truly* a constant, especially if it represents some kind of concept like a specific duration of time. We know that the milliseconds in an hour will never change, so it's appropriate here. Remember, this is only a convention. Not everyone will necessarily do things the same way. ### Indentation and line length Now it's time to head to more controversial topics. The war between coders that use tabs and coders that use spaces to indent their code is essentially a joke by now, as demonstrated in the [tabs versus spaces scene from the show Silicon Valley](https://www.youtube.com/watch?v=SsoOG6ZeyUI). -What actually matters is *consistency*. Choose a way to indent and stick to it. Various JS style-guides recommend different options, and one is not really superior to the other. A few popular ones are linked in the additional resources. +What actually matters is *consistency*. Choose a way to indent and stick to it. Various JavaScript style guides recommend different options, and one is not really superior to the other. We will look at style guides and related tools in more detail later in the curriculum. #### Line length -Again, different style guides will recommend different options for this one, but just about ALL of them suggest limiting the length of each line of code. +Again, different style guides will recommend different options for this one, but just about *all* of them suggest limiting the length of each line of code. Generally, your code will be easier to read if you manually break lines that are longer than about 80 characters. Many code editors have a line in the display to show when you have crossed this threshold. When manually breaking lines, you should try to break immediately *after* an operator or comma. @@ -162,21 +173,21 @@ let reallyReallyLongLine = oneMoreReallyLongThing; // Or maybe like this - let anotherReallyReallyLongLine = something + somethingElse + anotherThing + - howManyTacos + oneMoreReallyLongThing; +let anotherReallyReallyLongLine = something + somethingElse + anotherThing + + howManyTacos + oneMoreReallyLongThing; ``` +Different formats aren't necessarily right or wrong, and different people may prefer different things. Do things in a way that makes sense to you, and stay consistent with it. + ### Semicolons -Semicolons are *mostly* optional in JavaScript because the JS compiler will automatically insert them if they are omitted. This functionality CAN break in certain situations, leading to bugs in your code, so it is better to get used to adding semi-colons. +Semicolons are *mostly* optional in JavaScript because the JavaScript interpreter will automatically insert them if they are omitted. This functionality *can* break in certain situations, leading to bugs in your code, so we'd recommend getting used to adding semicolons. -Again: consistency is the main thing. +Whether you do or not, again, consistency is the main thing. ### About comments -Comments are a great tool. But like any good tool, it can be misused. Especially for someone early in their coding journey, it might be tempting to have comments that explain *everything* the code is doing. This is not a good practice. - -Next, we'll look into some common pitfalls in commenting and *why* they are pitfalls. +Comments are a great tool but like any good tool, they can be misused. Especially for someone early in their coding journey, it might be tempting to have comments that explain *everything* the code is doing. This is generally not a good practice. Let's look at some common pitfalls when commenting and *why* they are pitfalls. #### Don't comment when you should be using git @@ -206,49 +217,48 @@ theFunctionInUse(); #### Tell why, not how -The purpose of comments is not to provide pseudo code that duplicates your code. Good comments explain the *reasons* behind a piece of code. +Ideally, comments do not provide pseudocode that duplicates your code. Good comments explain the *reasons* behind a piece of code. Sometimes you won't even need a comment at all! -Let's look at an example to see this in practice: +Say we had a string where part of the text was inside square brackets and we wanted to extract the text within those brackets. ```javascript -// Bad Example - comment doesn't tell why, only what and how - -// This function increments the value of i by 1 -function incrementI(i) { - i = i + 1; // Add one to i - return i; +// Function to extract text +function extractText(s) { + // Return the string starting after the "[" and ending at "]" + return s.substring(s.indexOf("[") + 1, s.indexOf("]")); } +``` -// Better Example - comment tells a why +The comments just describe what we can tell from the code itself. Slightly more useful comments could explain the reasons behind the code. -// This function increments the value of index to move to the next element -function incrementI(i) { - i = i + 1; - return i; +```javascript +// Extracts text inside square brackets (excluding the brackets) +function extractText(s) { + return s.substring(s.indexOf("[") + 1, s.indexOf("]")); } +``` -// Good Example - the code tells all that is needed +But often, we can make the code speak for itself without comments. -function moveToNextElement(index) { - index = index + 1; - return index; +```javascript +function extractTextWithinBrackets(text) { + const bracketTextStart = text.indexOf("[") + 1; + const bracketTextEnd = text.indexOf("]"); + return text.substring(bracketTextStart, bracketTextEnd); } ``` -In the bad example, the comments explain twice what the code does. But for this, you could've just read the code, so the comments are redundant. - -In the better example, the comment clarifies the purpose of the function: moving to the next element. That's good, but we can do *even* better. +In the first example, the comments repeat twice what the code does. But for this, you could've just read the code, so the comments are redundant. -In the good example, no comments are needed at all. The use of descriptive functions and variable names eliminates the need for additional explanations. Pretty neat, huh? +In the second example, the comment clarifies the purpose of the function: extracting the text between square brackets from a string and not just "extracting text". That's handy, but we can do *even* better. -*This doesn't mean good code should lack comments*. In many situations, well-placed comments are priceless. The article linked in the assignment section goes into more depth on this. We don't want you to avoid comments; just be mindful of how they are best used. +In the last example, no comments are needed at all. The use of descriptive functions and variable names eliminates the need for additional explanations. Pretty neat, huh? -Let's look at one final example where a comment serves a good purpose: +**This doesn't mean good code should lack comments.** Let's look at an example where a comment serves a helpful purpose: ```javascript - function calculateBMI(height, weight) { - // The formula for BMI is weight in kilograms divided by height in meters squared + // The formula for BMI is weight in kilograms divided by height in meters squared const heightInMeters = height / 100; const bmi = weight / (heightInMeters * heightInMeters); return bmi; @@ -257,18 +267,22 @@ function calculateBMI(height, weight) { This comment helps to refresh the reader on how BMI is calculated in plain English, helping the reader to see why the height needs to be converted and what the following calculation is doing. We are almost there with the naming, but the comment still adds further clarity. +In many situations, well-placed comments are priceless. They might explain why an unintuitive bit of code is necessary, or perhaps the bigger picture of why a certain function is *particularly* important to be called here and not there. The article linked in the assignment section goes into more depth on this. + ### In conclusion -Now that we've covered these ideas, it's good to return to the reminder we shared at the start. Don't try to write perfectly clean code; this will only lead to frustration. Writing "spaghetti" is inevitable; everyone does it sometimes. Just keep these ideas in mind, and with time and patience, your code will start to get cleaner. +Now that we've covered these ideas, it's good to return to the reminder we shared at the start. Don't try to write perfectly clean code, this will only lead to frustration. Writing "spaghetti" is inevitable; everyone does it sometimes. Just keep these ideas in mind, and with time and patience, your code will start to get cleaner. Learning to write clean code is a process of constant improvement. One that will extend beyond you *completing* The Odin Project. This lesson is meant to serve as a primer and a starting point for that journey. +> Great code comes from experience. Experience comes from not-so-great code. + ### Assignment
1. Read [10 Principles for Keeping Your Programming Code Clean](https://onextrapixel.com/10-principles-for-keeping-your-programming-code-clean/) to get some great tips for clean code. -1. To help better understand good comment practices, read about [comments telling us how code works](https://blog.codinghorror.com/code-tells-you-how-comments-tell-you-why/) as well as how to [code without comments](https://blog.codinghorror.com/coding-without-comments/). +1. To help better understand good comment practices, read about [comments telling us why code works](https://blog.codinghorror.com/code-tells-you-how-comments-tell-you-why/) as well as how to [code without comments](https://blog.codinghorror.com/coding-without-comments/).
@@ -277,14 +291,14 @@ Learning to write clean code is a process of constant improvement. One that will The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. - [Why is it important to write clean code?](#introduction) -- [Name 5 clean code principles previously mentioned](https://onextrapixel.com/10-principles-for-keeping-your-programming-code-clean/) +- [What are some good principles for keeping code clean?](https://onextrapixel.com/10-principles-for-keeping-your-programming-code-clean/) - [What is the difference between good comments and bad comments?](https://onextrapixel.com/10-principles-for-keeping-your-programming-code-clean/) ### Additional resources This section contains helpful links to related content. It isn't required, so consider it supplemental. -- [A nice op-ed](https://www.martinfowler.com/bliki/CodeAsDocumentation.html) +- [A nice op-ed on code as documentation](https://www.martinfowler.com/bliki/CodeAsDocumentation.html) - [Airbnb style guide](https://github.com/airbnb/javascript) - [Chaining methods to write sentences](https://web.archive.org/web/20190211152543/https://javascriptissexy.com/beautiful-javascript-easily-create-chainable-cascading-methods-for-expressiveness/) - [Clean code in JavaScript](https://github.com/ryanmcdermott/clean-code-javascript) diff --git a/foundations/javascript_basics/data_types_and_conditionals.md b/foundations/javascript_basics/data_types_and_conditionals.md index 319aef14d20..9cee7c580cc 100644 --- a/foundations/javascript_basics/data_types_and_conditionals.md +++ b/foundations/javascript_basics/data_types_and_conditionals.md @@ -48,6 +48,14 @@ Note: Feel free to browse the files on the left column to gain familiarity with
+#### Replit fork limit + +Replit now limits free accounts to having 3 repls at a time. If you reach the limit of 3 repls, you can delete one or more of the previous forks to create a room for the new one. To do so, go to [your repls](https://replit.com/repls) and delete what you no longer need. + +
+ +
+ #### Replit and AI Replit recently introduced an AI assistant, which is on by default. Before trying any of the exercises, you should first disable it, in order to prevent it from spoiling the exercise. You can do so by clicking on the button labeled AI in the bottom left corner of the code view and then unchecking the "Enable" checkbox. diff --git a/foundations/javascript_basics/function_basics.md b/foundations/javascript_basics/function_basics.md index 9124da841b6..74b8c17faef 100644 --- a/foundations/javascript_basics/function_basics.md +++ b/foundations/javascript_basics/function_basics.md @@ -38,7 +38,7 @@ Here is a diagram to help you visualize how parameters are passed to a function, Make note of the fact that by calling `favoriteAnimal()` inside of `console.log()` with the argument `'Goat'` we get the return value of the function, string of `"Goat is my favorite animal!"`, printed to the console. We're passing in a function call `favoriteAnimal('Goat')` as an argument in a different function call - `log()`. -Keep this possibility in mind because you'll be passing in function calls as arguments somewhat often. If we just called the function without `console.log`ging what it returns, nothing would appear in the console **but** nonetheless the function would return that string. +Keep this possibility in mind because you'll be passing in function calls as arguments somewhat often. If we just called the function without using `console.log` to print it's return value, nothing would appear in the console **but** nonetheless the function would return that string. Feel free to experiment with the code on your own and replace `'Goat'` with your favorite animal. Notice how we can change the argument to anything we like? Try changing `animal` in the function declaration and in the function body, too. What happens when you do? diff --git a/foundations/javascript_basics/javascript_developer_tools.md b/foundations/javascript_basics/javascript_developer_tools.md index f015a07da50..aa9c11c8661 100644 --- a/foundations/javascript_basics/javascript_developer_tools.md +++ b/foundations/javascript_basics/javascript_developer_tools.md @@ -41,7 +41,7 @@ Google has updated some of the required sections in the below tutorials and some - Mobile Simulation 1. [Simulate mobile devices with Device Mode](https://developer.chrome.com/docs/devtools/device-mode/) - JavaScript - 1. [Debug JavaScript](https://developer.chrome.com/docs/devtools/javascript/) - Warning: In point 4 of step 3 of the tutorial, devtools will pause on the second line (`if (inputsAreEmpty()) {`) rather than at the declaration of the function. Don’t worry this is expected. + 1. [Debug JavaScript](https://developer.chrome.com/docs/devtools/javascript/) - Warning: In point 4 of step 3 of the tutorial, devtools will pause on the second line (`if (inputsAreEmpty()) {`) rather than at the declaration of the function. Don’t worry, this is expected. 1. [Pause your code with breakpoints](https://developer.chrome.com/docs/devtools/javascript/breakpoints/) 1. Go through the [Chrome DevTools console overview](https://developer.chrome.com/docs/devtools/console/) to familiarize yourself with the console and its usage. diff --git a/foundations/javascript_basics/object_basics.md b/foundations/javascript_basics/object_basics.md index 76acbe3671e..5037725aa14 100644 --- a/foundations/javascript_basics/object_basics.md +++ b/foundations/javascript_basics/object_basics.md @@ -11,6 +11,7 @@ This section contains a general overview of topics that you will learn in this l - Creating objects. - Accessing object properties. - Using multiple object operators. +- Understanding the differences between object and primitive data types. - Using the `map`, `filter` and `reduce` array methods. ### Objects @@ -20,6 +21,89 @@ Objects are a *very* important part of the JavaScript language, and while for th 1. This JavaScript.info [article on objects](https://javascript.info/object) is the best place to get started. 1. The [MDN tutorial on objects](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics) isn't bad either, so check it out if you need another take on the subject. +### Differences between objects and primitives + +Earlier in the curriculum you've learned about [primitive data types](https://www.theodinproject.com/lessons/foundations-data-types-and-conditionals). Now that you've seen the object data type, which includes but is not limited to, objects ({key: value}), arrays, and functions. The main difference between the two is that primitives can contain only a single thing (string, number, etc). Objects data types are used to store a collection of data and more complex entities. + +Besides the formal differences, there are also some technical differences which affect how we use each data type. When you define a primitive variable, it will contain a copy of the information provided to it: + +```javascript +let data = 42; +// dataCopy will store a copy of what data contains, so a copy of 42 +let dataCopy = data; + +// which means that making changes to dataCopy won't affect data +dataCopy = 43; + +console.log(data); // 42 +console.log(dataCopy); // 43 +``` + +On the other hand, when you define an object variable, it will contain a *reference* to the object provided to it: + +```javascript +// obj contains a reference to the object we defined on the right side +const obj = { data: 42 }; +// objCopy will contain a reference to the object referenced by obj +const objCopy = obj; + +// making changes to objCopy will make changes to the object that it refers to +objCopy.data = 43; + +console.log(obj); // { data: 43 } +console.log(objCopy); // { data: 43 } +``` + +This behavior isn't new to you. In your last project, you made changes to the cells in the Etch-A-Sketch grid by using references. Let's take this code snippet as an example: + +```javascript +const element = document.querySelector("#container"); +element.style.backgroundColor = "red"; +``` + +We're mutating the variable we declared (`element`), yet the changes affect the corresponding node in the DOM. Why does it happen? That's because the node we have in our code is a **reference** to the same node that our DOM uses. If that wasn't a reference, but a copy like primitive data types behave, our changes would have **no** effect! Because the changes would be made to the local copy we have. + +This behavior is also something to consider when we pass arguments to a function. Let's take the following functions for example: + +```javascript +function increaseCounterObject(objectCounter) { + objectCounter.counter += 1; +} + +function increaseCounterPrimitive(primitiveCounter) { + primitiveCounter += 1; +} + +const object = { counter: 0 }; +let primitive = 0; + +increaseCounterObject(object); +increaseCounterPrimitive(primitive); +``` + +Take a moment and guess what will happen to `object` and what will happen to `primitive` after we make the function calls. + +If you answered that the object counter would increase by 1, and the primitive counter wouldn't change, you're correct. Remember that the parameter `objectCounter` contains a *reference* to the same object as the `object` variable we gave it, while `primitiveCounter` contains only a copy of the primitive value only. + +
+ +#### Reassigning object data type variables + +While mutating the object we have a reference to will affect all other variables that reference it, reassigning a variable won’t affect what the other variables refer to. For example: + +```javascript +let animal = { species: "dog" }; +let dog = animal; + +// reassigning animal variable with a completely new object +animal = { species: "cat" }; + +console.log(animal); // { species: "cat" } +console.log(dog); // { species: "dog" } +``` + +
+ ### Intermediate/advanced array magic Besides being a quick and handy way to store data, arrays also have a set of functions for manipulating that data in very powerful ways. Once you begin to master these functions you will start to see ways to use them all over the place! There are really only a handful of these functions, but as you'll soon see, the possibilities of what you can do with them are near endless. @@ -177,9 +261,9 @@ function sumOfTripledEvens(array) {
-1. Start out by watching [JavaScript Array Cardio Practice - Day 1](https://www.youtube.com/watch?v=HB1ZC7czKRs) from Wes Bos. To follow along, fork and clone the [JavaScript30 repository](https://github.com/wesbos/JavaScript30). +1. Read through the [array method guide](https://javascript.info/array-methods) for a comprehensive overview of array methods in JavaScript. Complete the exercises at the end, except for "Create an extendable calculator," as it involves more advanced concepts that we have not yet covered. +1. Follow up by watching [JavaScript Array Cardio Practice - Day 1](https://www.youtube.com/watch?v=HB1ZC7czKRs) by Wes Bos. To follow along, fork and clone the [JavaScript30 repository](https://github.com/wesbos/JavaScript30). 1. Watch and code along with [Array Cardio Day 2](https://www.youtube.com/watch?v=QNmRfyNg1lw). -1. Read through the [array method guide](https://javascript.info/array-methods) for a more comprehensive and in-depth guide to array methods in JavaScript. Complete the exercises at the end except for "Create an extendable calculator", as that involves more advanced concepts we have not yet covered. 1. At this point you just need a little more practice! Go back to the [JavaScript exercises repository](https://github.com/TheOdinProject/javascript-exercises) that we introduced in the [Fundamentals Part 4](https://www.theodinproject.com/lessons/foundations-fundamentals-part-4) assignment. Review each README file prior to completing the following exercises in order: - `08_calculator` - `09_palindromes` @@ -199,6 +283,7 @@ The following questions are an opportunity to reflect on key topics in this less - [What is the difference between objects and arrays?](https://javascript.info/object#summary) - [How do you access object properties?](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics#bracket_notation) +- [How do primitives and object types differ when you assign them to other variables, or pass them into functions?](https://www.theodinproject.com/lessons/foundations-object-basics#differences-between-objects-and-primitives) - [What is `Array.prototype.map()` useful for?](https://www.youtube.com/watch?v=HB1ZC7czKRs&t=233s) - [What is `Array.prototype.filter()` useful for?](https://www.youtube.com/watch?v=HB1ZC7czKRs&t=84s) - [What is `Array.prototype.reduce()` useful for?](https://youtu.be/HB1ZC7czKRs?t=467) diff --git a/getting_hired/applying_and_interviewing/project_resume.md b/getting_hired/applying_and_interviewing/project_resume.md index 1e972b40b9e..26001c6c14b 100644 --- a/getting_hired/applying_and_interviewing/project_resume.md +++ b/getting_hired/applying_and_interviewing/project_resume.md @@ -14,7 +14,7 @@ Remember: ONE PAGE. - This Career Tool Belt article lists [6 free resume builder websites](https://web.archive.org/web/20230930114027/https://www.careertoolbelt.com/5-best-free-resume-builder-websites/) - [Novorésumé also has a free tier with templates available, as an alternate resource](https://novoresume.com/) -- Formatting could use some work, but here’s an [example resume from CareerCup.com](http://www.careercup.com/resume) +- Formatting could use some work, but here’s an [example resume from CareerCup.com](https://www.gayle.com/resume) - [Another great (totally free) resume builder](https://flowcv.io/) ### Optional reading diff --git a/git/foundations_git/commit_messages.md b/git/foundations_git/commit_messages.md index 659731d72c5..67c759c953b 100644 --- a/git/foundations_git/commit_messages.md +++ b/git/foundations_git/commit_messages.md @@ -68,6 +68,12 @@ Ahh, that's better! :) Now, developers can gain a better understanding of this c - Contains a body that provides a concise yet clear description of why the commit needed to be made (e.g., "Screen readers won't read the images to users with disabilities without this information"). - Separates the subject from the body with a new/blank line. This is a best practice we highly recommend following. It makes commit messages easier for other developers to read. +### How to commit with a subject and body in the message + +Up until now, you've been told to commit with `git commit -m `. To make a commit with subject and body in message, the simplest way is to type `git commit` without the `-m` flag and message argument. + +Doing so will open a new Visual Studio Code tab if you had [set Visual Studio Code as the Git editor](https://www.theodinproject.com/lessons/foundations-git-basics#changing-the-git-commit-message-editor). You can remove any comments and enter your multi-line messages. When you save and close the tab, your commit will be created. + ### When to commit A good way to view a commit is like a “snapshot” of your code at the moment that it was made. That version of your code up to that point will be saved for you to revert back to or look back at. diff --git a/git/foundations_git/introduction_to_git.md b/git/foundations_git/introduction_to_git.md index de8332bb4e0..a8046eb2e95 100644 --- a/git/foundations_git/introduction_to_git.md +++ b/git/foundations_git/introduction_to_git.md @@ -57,4 +57,4 @@ This section contains helpful links to related content. It isn't required, so co - [What is Git and GitHub?](https://content.red-badger.com/resources/what-is-git-and-github) - [What is version control?](https://www.atlassian.com/git/tutorials/what-is-version-control) -- [What is Git](https://www.atlassian.com/git/tutorials/what-is-git) +- [What is Git?](https://www.atlassian.com/git/tutorials/what-is-git) diff --git a/git/intermediate_git/a_deeper_look_at_git.md b/git/intermediate_git/a_deeper_look_at_git.md index e7ebe5482a1..7dad430b6e4 100644 --- a/git/intermediate_git/a_deeper_look_at_git.md +++ b/git/intermediate_git/a_deeper_look_at_git.md @@ -80,10 +80,13 @@ pick 92ad0af Create third file and create fourth file This would allow us to edit the typo in the `Create send file` commit to be `Create second file`. Perform similar changes in your interactive rebase tool, but don't copy and paste the above code since it won't work. Save and exit the editor, which will allow us to edit the commit with the following instructions: ```bash -You can amend the commit now, with - git commit --amend -Once you're satisfied with your changes, run - git rebase --continue +git commit --amend +``` + +The command above will allow you to amend the commit. Once you're satisfied with your changes, you can complete the rebase with the following: + +```bash +git rebase --continue ``` So let's edit our commit by typing `git commit --amend`, fixing the typo in the title, and then finishing the rebase by typing `git rebase --continue`. That's all there is to it! Have a look at your handiwork by typing `git log`, and seeing the changed history. It seems simple, but this is a very dangerous tool if misused, so be careful. Most importantly, remember that **if you have to rebase commits in a shared repository, make sure you're doing so for a very good reason that your coworkers are aware of.** @@ -106,10 +109,10 @@ Rename the commit to `Create first and second file`, then finish the rebase. Tha Before diving into Remotes, we're going to have a look at a handy Git command called `git reset`. Let's have a look at the commit `Create third file and create fourth file`. At the moment we're using blank files for convenience, but let's say these files contained functionality and the commit was describing too much at once. In that case what we could do is split it up into two smaller commits by, once again, using the interactive `rebase` tool. -We can open up the tool just like last time, change `pick` to `edit` for the commit we're going to split. But instead, what we're going to do is run `git reset HEAD^`, which resets the commit to the one right before HEAD. This allows us to add the files individually and commit them individually. All together it would look something like this: +We can open up the tool just like last time, change `pick` to `edit` for the commit we're going to split. But instead, what we're going to do is run `git reset HEAD~`, which resets the commit to the one right before HEAD. This allows us to add the files individually and commit them individually. All together it would look something like this: ```bash -git reset HEAD^ +git reset HEAD~ git add test3.md && git commit -m 'Create third file' git add test4.md && git commit -m 'Create fourth file' ``` @@ -148,9 +151,9 @@ You might be feeling overwhelmed at this point, so let's recap what we've learne The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. -- Explain what it means for branches to be pointers. -- How can you amend your last commit? -- What are some different ways to rewrite history? +- [Explain what it means for branches to be pointers.](https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell) +- [How can you amend your last commit?](https://git-scm.com/book/en/v2/Git-Basics-Undoing-Things) +- [What are some different ways to rewrite history?](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History) ### Additional resources diff --git a/git/intermediate_git/using_git_in_the_real_world.md b/git/intermediate_git/using_git_in_the_real_world.md index 7227d853292..bb2473669e4 100644 --- a/git/intermediate_git/using_git_in_the_real_world.md +++ b/git/intermediate_git/using_git_in_the_real_world.md @@ -2,7 +2,7 @@ Git basics are very straightforward, but it sometimes feels like a bottomless pit when you find yourself on the wrong side of a confusing error situation. It's doubly frustrating because you think that messing up or trying the wrong solution can lose data. It's actually very hard to "lose" data with Git but it can certainly be hiding somewhere you wouldn't think to look without an experienced dev poking around. -The thing about Git is that, unless you've got a seriously impressive memory, you can't just learn it by reading about it up front... you need to do it. Find a problem you want to go back and fix, hit an error in your merge, etc. and Google the hell out of it, learning a new Git tactic in the process. +The thing about Git is that, unless you've got a seriously impressive memory, you can't just master it by reading about it; you need hands-on practice! For example, find a problem you want to fix, run into a merge error, and then dive into Google to learn a new Git technique along the way to help you fix that problem. To help you out, come back and refer to this lesson again when you're in trouble. We'll first cover a real-world example of a GitHub workflow used on this very project. The Additional Resources section below should also help you find high quality resources for when you need them later on. @@ -17,7 +17,9 @@ This section contains a general overview of topics that you will learn in this l Before we dive into workflows, take a minute to remind yourself about good commit messages. You can check the [Commit Messages lesson](https://www.theodinproject.com/lessons/foundations-commit-messages) for a reminder. This is a good time to draw particular attention to [Conventional Commits](https://www.conventionalcommits.org), a standard for commits that is gaining more and more popularity for collaborative projects. It helps to make sure your commit message gives a clear description of its purpose to anyone reading. You may like to implement these going forwards (if you aren't already!), or at least be aware of them for when you read other repos. -### A Git workflow for open source contribution +### Assignment + +
Let's say you want to contribute to [our curriculum repo](https://github.com/TheOdinProject/curriculum/). @@ -59,13 +61,15 @@ Note that a `git fetch upstream` followed by a `git merge upstream/some_branch` 1. If you have been following along with the above steps to get familiar with this workflow, you should **stop at this point**. If you have completed an assigned issue, the final step is to submit a pull request to merge your feature branch into the original `upstream` repository's `main` branch. This can be done using GitHub's interface. 1. Shake your moneymaker, you're an OSS contributor! +
+ ### Knowledge check The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. - [What name is typically given for a Git remote that points to a repo that's been forked?](#initial-setup) - [Can you directly send your changes to a repository that you don't own/have write access to?](#sending-your-pull-request) -- [What should you do immediately before merging your feature branch into main?](#ongoing-workflow) +- [What should you do immediately before merging main into your feature branch?](#ongoing-workflow) ### Additional resources diff --git a/git/intermediate_git/working_with_remotes.md b/git/intermediate_git/working_with_remotes.md index 109b3a00d6d..a02fa55defa 100644 --- a/git/intermediate_git/working_with_remotes.md +++ b/git/intermediate_git/working_with_remotes.md @@ -28,7 +28,7 @@ git log ``` -Huh, that's interesting. We don't see our fourth file on our local system. Let's check our GitHub repository to see if it's there. +Huh, that's interesting. We can’t find our fourth file on our local system. Let's check our GitHub repository to see if it's there. Oh no, we just destroyed it! In this scenario, the danger - you could potentially destroy the work of those you're collaborating with! `git push --force` is a **very dangerous command, and it should be used with caution when collaborating with others**. Instead, you can fix your outdated history error by updating your local history using `fetch`, `merge`, and then attempting to `push` again. @@ -89,7 +89,7 @@ Let's review the dangers we've addressed so far. I know, I know, it's scary stuf The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. -- [What is a safe way to push history changes to a remote repository?](#force-with-lease) +- [What is a safe way to forcefully push history changes to a remote repository?](#force-with-lease) - [What are the dangers of history-changing operations?](#dangers) - [What are best practices of history-changing operations?](#best-practices) diff --git a/intermediate_html_css/forms/project_sign_up_form.md b/intermediate_html_css/forms/project_sign_up_form.md index bd4b49bfb09..cdbc50b9d30 100644 --- a/intermediate_html_css/forms/project_sign_up_form.md +++ b/intermediate_html_css/forms/project_sign_up_form.md @@ -25,7 +25,7 @@ This project is intended to give you a chance to flex some of the new items you' 1. The color we've chosen for the 'Create Account' button is similar to tones found in the background image. Specifically, it is `#596D48`. 1. The inputs, by default have a very light border (`#E5E7EB`), but we’ve included 2 variations. For starters, the password inputs should have a red border if they contain an invalid password. This can be handled with the `:invalid` pseudo-class you've learned in the previous lesson. 1. The other variation is the selected input, which should have a blue border and subtle box-shadow. This can be done with the `:focus` pseudo-class you've learned about in an earlier lesson. -1. Do not worry about making your project look nice on mobile, but DO resize your browser a little bit to make sure that it's not completely broken at different desktop resolutions. +1. Do not worry about making your project look nice on mobile. Responsive design isn't covered until later in the curriculum. 1. Validating that the password fields match each other requires JavaScript. Using JavaScript to validate forms is covered in a future lesson. For now, just validate each field separately.
diff --git a/intermediate_html_css/grid/introduction_to_grid.md b/intermediate_html_css/grid/introduction_to_grid.md index 7be658bca3a..c7ee97f5ba1 100644 --- a/intermediate_html_css/grid/introduction_to_grid.md +++ b/intermediate_html_css/grid/introduction_to_grid.md @@ -20,19 +20,25 @@ The Flex lessons covered positioning items along the [two flex axes (main and cr You’ll remember you can line up a nice row of flex items like this:

+ See the Pen Single Row | CSS Flexbox by TheOdinProject (@TheOdinProjectExamples) on CodePen. +

+ Or a column like this:

+ See the Pen Single Column | CSS Flexbox by TheOdinProject (@TheOdinProjectExamples) on CodePen. +

+ For one-dimensional layouts, Flex offers a convenient tool without having to rely on floats or CSS hacks to align your items properly. @@ -48,10 +54,13 @@ We know that was a frustrating one, but it's part of the point. While Flexbox al But setting up a two-dimensional layout of cards would be much easier using CSS Grid:

+ See the Pen 2D Layout | CSS Grid by TheOdinProject (@TheOdinProjectExamples) on CodePen. +

+ ### What is grid? @@ -68,7 +77,7 @@ While some people thought CSS Grid was here to replace Flexbox, you will learn b ### Knowledge check -This section contains questions for you to check your understanding of this lesson. If you’re having trouble answering the questions below on your own, review the material above to find the answer. +The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. - [How can you use Flex to make a two-dimensional layout?](#a-look-back-at-flex) - [Why was CSS Grid introduced?](#what-is-grid) @@ -76,7 +85,7 @@ This section contains questions for you to check your understanding of this less ### Additional resources -This section contains helpful links to other content. It isn’t required, so consider it supplemental. +This section contains helpful links to related content. It isn't required, so consider it supplemental. - Watch [Flexbox vs. CSS Grid — Which is Better?](https://www.youtube.com/watch?v=hs3piaN4b5I) for a visual representation of the use cases for Flexbox vs CSS Grid - Read CSS Tricks' quick take on the [differences between flex and grid](https://css-tricks.com/quick-whats-the-difference-between-flexbox-and-grid/). diff --git a/intermediate_html_css/intermediate_css_concepts/advanced_selectors.md b/intermediate_html_css/intermediate_css_concepts/advanced_selectors.md index a2b8dc75f77..17663665317 100644 --- a/intermediate_html_css/intermediate_css_concepts/advanced_selectors.md +++ b/intermediate_html_css/intermediate_css_concepts/advanced_selectors.md @@ -283,7 +283,7 @@ This section contains helpful links to related content. It isn't required, so co - [Kevin Powell](https://www.youtube.com/kepowob/search?query=pseudo) has a variety of videos on several of these topics if you'd like a deeper dive. - [The CSS Tricks Almanac](https://css-tricks.com/almanac/selectors/) has a great reference for all pseudo-elements and selectors. It includes examples, extra resources and browser support charts. -- [W3 Schools](https://www.w3schools.com/cssref/css_selectors.asp) also has a solid, more concise reference list. Includes an interactive selector tool if you'd like to play around with some hands on examples. +- [W3 Schools](https://www.w3schools.com/cssref/css_selectors.asp) also has a solid, more concise reference list. Includes an interactive selector tool if you'd like to play around with some hands-on examples. - [The Free Code Camp Selector Cheat Sheet](https://www.freecodecamp.org/news/css-selectors-cheat-sheet/) has a solid summary of some of the most common selectors. - A nice concise article on the [differences between pseudo-classes and pseudo-elements](https://www.growingwiththeweb.com/2012/08/pseudo-classes-vs-pseudo-elements.html). Also provides a solid summary of the different kinds of selectors. - [Smashing Magazine on Taming Advanced CSS Selectors](http://coding.smashingmagazine.com/2009/08/17/taming-advanced-css-selectors/) diff --git a/intermediate_html_css/intermediate_css_concepts/default_styles.md b/intermediate_html_css/intermediate_css_concepts/default_styles.md index 01a1430a09b..d4d7480ddbb 100644 --- a/intermediate_html_css/intermediate_css_concepts/default_styles.md +++ b/intermediate_html_css/intermediate_css_concepts/default_styles.md @@ -11,7 +11,7 @@ This section contains a general overview of topics that you will learn in this l ### What are default styles and where do they come from? -As you have worked on projects, you likely observed default styles applied to certain elements, such as larger and bolder headings on `h1` elements, and blue, underlined links on `a' elements. There is also a good chance you struggled with things like default margins and padding. These styles are part of the user-agent stylesheets, ensuring basic styling for webpages without CSS. Each browser has its own set of user-agent stylesheets so the default styles do vary slightly between browsers. +As you have worked on projects, you likely observed default styles applied to certain elements, such as larger and bolder headings on `h1` elements, and blue, underlined links on `a` elements. There is also a good chance you struggled with things like default margins and padding. These styles are part of the user-agent stylesheets, ensuring basic styling for webpages without CSS. Each browser has its own set of user-agent stylesheets so the default styles do vary slightly between browsers. ### What if I don't like the defaults? diff --git a/intermediate_html_css/intermediate_css_concepts/positioning.md b/intermediate_html_css/intermediate_css_concepts/positioning.md index 46c56320573..208c7d760ab 100644 --- a/intermediate_html_css/intermediate_css_concepts/positioning.md +++ b/intermediate_html_css/intermediate_css_concepts/positioning.md @@ -43,7 +43,7 @@ Fixed elements are also removed from the normal flow of the document and are pos ### Sticky positioning -Sticky elements will act like normal elements until you scroll past them, then they start behaving like fixed elements. They are also not taken out of the normal flow of the document. It might sound confusing, so check out this [example of sticky positioning](https://codepen.io/theanam/pen/MPLBYy) example might clear things up for you. It's useful for things like section-headings. Remember being able to still see what category you're looking at while scrolling through a shop? This is how it's done! +Sticky elements will act like normal elements until you scroll past them, then they start behaving like fixed elements. They are also not taken out of the normal flow of the document. It might sound confusing, so check out this [sticky positioning example](https://codepen.io/theanam/pen/MPLBYy) that might clear things up for you. It's useful for things like section-headings. Remember being able to still see what category you're looking at while scrolling through a shop? This is how it's done! ### Assignment diff --git a/javascript/asynchronous_javascript_and_apis/project_weather_app.md b/javascript/asynchronous_javascript_and_apis/project_weather_app.md index f09943aecb1..b4bb9cb85cb 100644 --- a/javascript/asynchronous_javascript_and_apis/project_weather_app.md +++ b/javascript/asynchronous_javascript_and_apis/project_weather_app.md @@ -1,34 +1,26 @@ ### Introduction -Use everything we've been discussing to create a weather forecast site using the weather API from the previous lesson. You should be able to search for a specific location and toggle displaying the data in Fahrenheit or Celsius. +Use everything we've been discussing to create a weather forecast site using the Visual Crossing API from previous lessons. You should be able to search for a specific location and toggle displaying the data in Fahrenheit or Celsius. You should change the look of the page based on the data, maybe by changing the color of the background or by adding images that describe the weather. (You could even use the Giphy API to find appropriate weather-related gifs and display them). Feel free to use promises or async/await in your code, though you should try to become comfortable with both. -
- -#### WeatherAPI free tier - -After creating your API key from WeatherAPI, you will automatically be moved to the free tier after 14 days. This will limit the forecast data available to you to 3 days. You may want to keep this in mind while making design choices for the forecast display. - -
- ### API keys, secrets, and security Not all APIs are free, and depending on how they're set up, they can cost money per use. This makes them a prime target for people looking to use the API without paying by using **your** API key. They can also be rate-limited, and if someone has access to your API key they can use up all of your uses. One way to prevent this issue is to store your API keys on the server and never send them to the frontend in the first place, this is often done using environment variables and it makes the key available only on the server the code is deployed to. -When talking about API keys and security you'll often hear "Never trust the client" (client meaning the frontend). Often this means not to trust that data coming *from* the client is valid, but it also means that you cannot trust anything we send *to* the client. Because of this, when you leak an API key, Github will alert you that you have committed an API key publicly. After following this project, and indeed exposing the API key, you may notice that Github will send you this alert. This is totally OK for this project as this API key is publicly available and there is no consequence for exposing it. This is not to say ALL keys are this way. Later during the backend courses you will learn ways to securely deal with these topics. +When talking about API keys and security you'll often hear "Never trust the client" (client meaning the frontend). Often this means not to trust that data coming *from* the client is valid, but it also means that you cannot trust anything we send *to* the client. Because of this, when you leak an API key, Github will alert you that you have committed an API key publicly. After following this project, and indeed exposing the API key, you may notice that Github will send you this alert. This is totally OK for this project as this API key is publicly available and there is no consequence for exposing it. This is not to say ALL keys are this way. Later during the backend courses you will learn ways to securely deal with these topics. ### Assignment
1. Set up a blank HTML document with the appropriate links to your JavaScript and CSS files. -2. Write the functions that hit the API. You're going to want functions that can take a location and return the weather data for that location. For now, just `console.log()` the information. -3. Write the functions that _process_ the JSON data you're getting from the API and return an object with only the data you require for your app. -4. Set up a form that will let users input their location and will fetch the weather info (still just `console.log()` it). -5. Display the information on your webpage! -6. Add any styling you like! -7. Optional: add a 'loading' component that displays from the time the form is submitted until the information comes back from the API. Use DevTools to test for low-end devices. -8. Push that baby to github and share your solution below! +1. Write the functions that hit the API. You're going to want functions that can take a location and return the weather data for that location. For now, just `console.log()` the information. +1. Write the functions that *process* the JSON data you're getting from the API and return an object with only the data you require for your app. +1. Set up a form that will let users input their location and will fetch the weather info (still just `console.log()` it). +1. Display the information on your webpage! +1. Add any styling you like! +1. Optional: add a 'loading' component that displays from the time the form is submitted until the information comes back from the API. Use DevTools to test for low-end devices. +1. Push that baby to github and share your solution below!
diff --git a/javascript/asynchronous_javascript_and_apis/working_with_apis.md b/javascript/asynchronous_javascript_and_apis/working_with_apis.md index cd8e2c0154d..8082e736673 100644 --- a/javascript/asynchronous_javascript_and_apis/working_with_apis.md +++ b/javascript/asynchronous_javascript_and_apis/working_with_apis.md @@ -15,42 +15,52 @@ This section contains a general overview of topics that you will learn in this l Servers that are created for serving data for external use (in websites or apps) are often referred to as APIs or ['Application Programming Interfaces'](https://www.youtube.com/watch?v=s7wmiS2mSXY). -There are multiple ways of requesting data from an API, but all of them basically do the same thing. For the most part, APIs are accessed through URLs, and the specifics of how to query these URLs change based on the specific service you are using. For example, WeatherAPI has several types of data that you can request. To get the current weather in a specific location, you can pass in the name of a city (optionally, you can also pass a zip code & even an ip-address!) as a URL query string parameter, like so: +There are multiple ways of requesting data from an API, but all of them basically do the same thing. For the most part, APIs are accessed through URLs, and the specifics of how to query these URLs change based on the specific service you are using. For example, [Visual Crossing](https://www.visualcrossing.com/weather-api) has a weather API that has several types of data you can request. To get the current weather in a specific location, you can pass in the name of a city into the path of the URL, like so: ```text -https://api.weatherapi.com/v1/current.json?q=london +https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/london ``` -The specifics for using any API are usually documented on the service's website. Check the [WeatherAPI documentation](https://www.weatherapi.com/docs/). If you haven't already, go ahead and paste the weather URL above, with the city of your choice, into your browser... (we'll wait). +The specifics for using any API are usually documented on the service's website. Check out the [Visual Crossing API Documentation](https://www.visualcrossing.com/resources/documentation/weather-api/timeline-weather-api/). If you haven't already, go ahead and paste the weather URL above, with the city of your choice, into your browser... (we'll wait). You'll probably get an error like this: ```text -{{"error":{"code":1002,"message":"API key is invalid or not provided."}}} +No API key or session found. Please verify that your API key parameter is correct. ``` -This brings us to another point about APIs. In most cases, you will have to create an account and request an "API key" from the API service before attempting to fetch data from their endpoints (specific URLs that you use to access a particular function or data within the API). Once obtained, an API key will usually have to be included with every data request, such as *another* URL query string parameter: +This brings us to another point about APIs. In most cases, you will have to create an account and request an "API key" from the API service before attempting to fetch data from their endpoints (specific URLs that you use to access a particular function or data within the API). Once obtained, an API key will usually have to be included with every data request. With Visual Crossing, that's as a query string parameter: ```text -https://api.weatherapi.com/v1/current.json?key=11111111111111111&q=london +https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/london?key=11111111111111111 ``` -As you can imagine, an API key is random and unique to you. As such, services like WeatherAPI can correlate your API key to your requests of their data, including how much and how often you are requesting it. +As you can imagine, an API key is random and unique to you. As such, services like Visual Crossing can correlate your API key to your requests of their data, including how much and how often you are requesting it. -On one hand, issuing API keys allows an API service to better track abuse of their systems and data. On the other hand, it can also be a way for those services to mitigate and recuperate operating costs. WeatherAPI, for example, provides not only a free tier but a variety of paid tiers that can cost up to 65 USD/month! After all, running servers costs money, and APIs are no exception. While a single request to an API might cost a fraction of a penny, imagine using that API to create an amazing weather app that gets used all over the world... you could easily have thousands of people accessing that data every minute! The cost to handle that traffic could quickly balloon up to significant sums for the API service. +Issuing API keys allows an API service to better track abuse of their systems and data. Additionally, it can also be a way for those services to mitigate and recuperate operating costs. Visual Crossing, for example, provides not only a free tier but a variety of paid tiers that can cost up to 150 USD/month! After all, running servers costs money, and APIs are no exception. While a single request to an API might cost a fraction of a penny, imagine using that API to create an amazing weather app that gets used all over the world... you could easily have thousands of people accessing that data every minute! The cost to handle that traffic could quickly balloon up to significant sums for the API service. -As such, you'll find that most API services, if not all, provide paid tiers that come with the ability to make more frequent requests, or provide access to more information unavailable in lower tiers. For example, WeatherAPI's free plan only allows your app to make a monthly total of 1 million requests and limits the information provided, while the "Business" tier allows up to 10,000,000 requests per month and gives you all of the available information! The free tier also comes with basic hourly and daily forecasting data, but it does not include data for a 30-day forecast ([details about the WeatherAPI tiers](https://www.weatherapi.com/pricing.aspx) if you're interested). So, if your app becomes successful and needs additional features, you'll probably need to pay for a better account. +As such, you'll find that most API services, if not all, provide paid tiers that come with the ability to make more frequent requests, or provide access to more information unavailable in lower tiers. For example, Visual Crossing's free version allows 1000 calls/requests per day with a limited amount of information (albeit sufficient for a pet project). On the other hand, the Enterprise version provides unlimited API calls per month, has Energy data, Maritime data... all those bells and whistles ([details about Visual Crossing's pricing](https://www.visualcrossing.com/weather-data-editions) if you're curious). So, if your app becomes successful and needs additional features, you'll probably need to pay for a better account. Because your API key is **your** key to these services and data, securing them is an important habit, especially if you are using a paid tier. There are plenty of bots that crawl GitHub repositories solely for hardcoded/unsecured API keys, allowing bad agents to then access and [utilize the services and data you've paid for](https://web.archive.org/web/20150102022540/http://www.devfactor.net/2014/12/30/2375-amazon-mistake/). In fact, the more eagle-eyed readers may have noticed a problem with the demonstration above: The API key is right there in the URL request. It would not take much for an internet traffic sniffer to pick up on the API key, least of all someone looking over your shoulder! -At this point in the curriculum, though, this point is largely moot. After all, we're leveraging free access to APIs, and the majority of our apps are only going to be used by us and the people that view our portfolios. Just make a note of the severe limitations of using API keys as demonstrated above for now. The basics of securing and obfuscating API keys from GitHub and from your requests will be covered later in the curriculum. +At this point in the curriculum, though, this point is largely moot. After all, we're leveraging free access to APIs, and the majority of our apps are only going to be used by us and the people that view our portfolios. Just make a note of the severe limitations of using API keys as demonstrated above for now. Securing API keys requires handling things server-side, and we are only focusing on the frontend concepts here. If you are in the Full Stack JavaScript pathway, the backend will be covered later in the curriculum. -Back to WeatherAPI. Go ahead and [create an account](https://www.weatherapi.com/signup.aspx) to obtain an API key from their free tier. Once the key has been activated, try making a new request with the city of your choice AND the API key passed in as query string parameters, like the example above. You'll hopefully see a proper response, something like: +Back to Visual Crossing. Go ahead and [create a free Visual Crossing account](https://www.visualcrossing.com/sign-up) to obtain an API key. You can find your API key in your account profile page. Once you have your key, try making a new request with the city of your choice, and the API key passed in as query string parameters, like the example above. You'll hopefully see a proper response, something like: ```JSON -{"location":{"name":"London","region":"City of London, Greater London","country":"United Kingdom","lat":51.52,"lon":-0.11,"tz_id":"Europe/London","localtime_epoch":1676482062,"localtime":"2023-02-15 17:27"},"current":{"temp_c":13.0,"temp_f":55.4,"is_day":0,"condition":{"text":"Clear","icon":"//cdn.weatherapi.com/weather/64x64/night/113.png","code":1000},"wind_mph":12.5,"wind_kph":20.2,"wind_degree":210,"wind_dir":"SSW","pressure_mb":1022.0,"pressure_in":30.18,"precip_mm":0.0,"precip_in":0.0,"humidity":58,"cloud":0,"feelslike_c":11.7,"feelslike_f":53.1,"vis_km":10.0,"vis_miles":6.0,"uv":4.0,"gust_mph":12.1,"gust_kph":19.4}} +{"queryCost":1,"latitude":51.5064,"longitude":-0.12721,"resolvedAddress":"London, England, United Kingdom","address":"london","timezone":"Europe/London","tzoffset":1.0,"description":"Similar temperatures continuing with a chance of rain tomorrow, Tuesday & Thursday.","days":[{"datetime":"2024-07-06","datetimeEpoch":1720220400,"tempmax":61.4,"tempmin":53.1,"temp":57.8,"feelslikemax":61.4,"feelslikemin":53.1,"feelslike":57.8,"dew":51.3,"humidity":79.7,"precip":0.457,"precipprob":100.0,"precipcover":75.0,"preciptype":["rain"],"snow":0.0,"snowdepth":0.0,"windgust":35.3,"windspeed":21.9,"winddir":262.6,"pressure":1001.8,"cloudcover":70.5,"visibility":8.3,"solarradiation":147.5,"solarenergy":12.9,"uvindex":6.0,"severerisk":10.0,"sunrise":"04:52:02","sunriseEpoch":1720237922,"sunset":"21:18:20","sunsetEpoch":1720297100,"moonphase":0.02,"conditions":"Rain, Partially cloudy","description":"Partly cloudy throughout the day with a chance of rain throughout the day.","icon":"rain","stations":["EGWU","EGLL","D5621","EGLC"]}]} ``` +(This preview above is just the tip of the iceberg, the actual response is a lot longer!) + +
+ +#### Visual Crossing's query builder + +Curious how to construct queries? Check out [Visual Crossing's query builder](https://www.visualcrossing.com/weather/weather-data-services)! This will help you build a query with the region as the only input. Play around with the location and query options. Neat, isn't it? The output uses the "Grid" tab, but our query is in the "API" tab, and we want to learn *how* the query was structured. Click on the "API" tab and it will show the query that led to the grid format you just saw. + +
+ Congratulations on making your first API request! ### Fetching data @@ -99,7 +109,7 @@ fetch('https://url.com/some/url') In case you've forgotten, scroll back up and look at how you would use XHR to do the same thing. While you're admiring how nice and clean that code is, notice the `.then()` and `.catch()` functions there. Do you remember what those are? (PROMISES!) -Let's change up our API for this example. We're going to walk through an example using fetch with the [giphy](https://giphy.com/) API to display a random gif on a webpage. The API requires you to sign up and get a free API key, so go ahead and [do that](https://developers.giphy.com/docs/api#quick-start-guide). +Let's change up our API for this example. We're going to walk through an example using fetch with the [giphy](https://giphy.com/) API to display a random gif on a webpage. The API requires you [sign up to giphy and get a free API key](https://developers.giphy.com/docs/api/#quick-start-guide). Giphy has several methods for searching and finding GIFs which you can read about in their documentation. Today we're just going to use the 'translate' endpoint because it's the simplest one for our purposes. You can find the appropriate URL in their documentation by scrolling down [to the translate endpoint information from Giphy](https://developers.giphy.com/docs/api/endpoint#translate). What it tells us is that the correct URL is `api.giphy.com/v1/gifs/translate` and that it requires 2 parameters, your `api_key` and a `search term`. If you put it all together correctly (with YOUR API key) you should get something like this: @@ -214,7 +224,7 @@ Running the file should now log the URL of the image. All that's left to do is s If all goes well, you should see a new image on the page every time you refresh! -If you've gotten lost along the way, check out this [jsbin project](http://jsbin.com/canofar/edit?html,output). Besides the glorious styling, this is what your version should look like. +If you've gotten lost along the way, check out this [jsbin project demonstrating fetching from giphy](http://jsbin.com/canofar/edit?html,output). Besides the glorious styling, this is what your version should look like. While we are pushing this API key to the frontend, this isn't something you should do with any key that is not free. Keys used on the client-side are considered public knowledge, so caution must be taken with sensitive and non-free keys. Handling keys without pushing them to the frontend will be taught in later sections if you haven't already learned it in the Ruby course. diff --git a/javascript/computer_science/a_very_brief_intro_to_cs.md b/javascript/computer_science/a_very_brief_intro_to_cs.md index c046c275c70..7c8ebf67912 100644 --- a/javascript/computer_science/a_very_brief_intro_to_cs.md +++ b/javascript/computer_science/a_very_brief_intro_to_cs.md @@ -25,6 +25,7 @@ This section contains a general overview of topics that you will learn in this l 1. Watch [What is an Algorithm?](https://youtu.be/e_WfC8HwVB8) on YouTube for a more structured look at solving problems using algorithms. 1. Read this Quora answer about the [importance of algorithms in web development](https://qr.ae/py3NAc) to get some context for why we're going over this stuff. 1. Watch [What is pseudocode?](https://www.youtube.com/watch?v=Rg-fO7rDsds) + 1. Watch the first section (from 0:00 - 7:01) of [Telusko's video on data structures and algorithms](https://www.youtube.com/watch?v=xWLxhF3b5P8) for a quick overview of DSA, and why companies may be interesting in hiring candidates familiar with DSA.
diff --git a/javascript/computer_science/hash_map_data_structure.md b/javascript/computer_science/hash_map_data_structure.md index 2e0be6e0e09..f894a87ed2e 100644 --- a/javascript/computer_science/hash_map_data_structure.md +++ b/javascript/computer_science/hash_map_data_structure.md @@ -216,3 +216,4 @@ This section contains helpful links to related content. It isn't required, so co - This discussion goes through the [usages of prime numbers in hash functions](https://stackoverflow.com/questions/299304/why-does-javas-hashcode-in-string-use-31-as-a-multiplier/299748). - The [pigeonhole principle](https://en.wikipedia.org/wiki/Pigeonhole_principle) mathematically guarantees collisions when there are more nodes than boxes. +- Check out [Hashing](https://samwho.dev/hashing/) if you want to get a better fundamental understanding of hash functions. diff --git a/javascript/computer_science/project_binary_search_trees.md b/javascript/computer_science/project_binary_search_trees.md index 90ffb1854e9..62aa3ab9565 100644 --- a/javascript/computer_science/project_binary_search_trees.md +++ b/javascript/computer_science/project_binary_search_trees.md @@ -43,9 +43,9 @@ You'll build a balanced BST in this assignment. Do not use duplicate values beca 1. Write a `find(value)` function that returns the node with the given value. -1. Write a `levelOrder(callback)` function that accepts an optional callback function as its parameter. `levelOrder` should traverse the tree in breadth-first level order and provide each node as an argument to the callback. As a result, the callback will perform an operation on each node following the order in which they are traversed. `levelOrder` may be implemented using either iteration or recursion (try implementing both!). The method should return an array of values if no callback is given as an argument. **Tip:** You will want to use an array acting as a queue to keep track of all the child nodes that you have yet to traverse and to add new ones to the list ([video on level order traversal](https://www.youtube.com/watch?v=86g8jAQug04)). +1. Write a `levelOrder(callback)` function that accepts a callback function as its parameter. `levelOrder` should traverse the tree in breadth-first level order and call the callback on each node as it traverses, passing the whole node as an argument, similarly to how `Array.prototype.forEach` might work for arrays. `levelOrder` may be implemented using either iteration or recursion (try implementing both!). If no callback function is provided, [throw an Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw) reporting that a callback is required. **Tip:** You will want to use an array acting as a queue to keep track of all the child nodes that you have yet to traverse and to add new ones to the list ([video on level order traversal](https://www.youtube.com/watch?v=86g8jAQug04)). -1. Write `inOrder(callback)`, `preOrder(callback)`, and `postOrder(callback)` functions that also accept an optional callback as a parameter. Each of these functions should traverse the tree in their respective depth-first order and yield each node to the provided callback. The functions should return an array of values if no callback is given as an argument. +1. Write `inOrder(callback)`, `preOrder(callback)`, and `postOrder(callback)` functions that also accept a callback as a parameter. Each of these functions should traverse the tree in their respective depth-first order and pass each node to the provided callback. The functions should throw an Error if no callback is given as an argument, like with `levelOrder`. 1. Write a `height(node)` function that returns the given node's height. Height is defined as the number of edges in the longest path from a given node to a leaf node. diff --git a/javascript/computer_science/project_linked_lists.md b/javascript/computer_science/project_linked_lists.md index ad19223dfcd..4944ce95cb8 100644 --- a/javascript/computer_science/project_linked_lists.md +++ b/javascript/computer_science/project_linked_lists.md @@ -57,10 +57,39 @@ Build the following functions in your linked list class / factory: 1. `toString` represents your LinkedList objects as strings, so you can print them out and preview them in the console. The format should be: `( value ) -> ( value ) -> ( value ) -> null` -### Extra credit +#### Extra credit 1. `insertAt(value, index)` that inserts a new node with the provided `value` at the given `index`. 1. `removeAt(index)` that removes the node at the given `index`. **Extra Credit Tip:** When you insert or remove a node, consider how it will affect the existing nodes. Some of the nodes will need their `nextNode` link updated. + +#### Test it out + +Let's test out the Linked List you made! + +1. Create a `main.js` file and make sure it imports your `LinkedList` class or factory. This is where we'll test the list. +1. Create an instance of your `LinkedList` and populate it with nodes: + + ```javascript + // example uses class syntax - adjust as necessary + const list = new LinkedList(); + + list.append("dog"); + list.append("cat"); + list.append("parrot"); + list.append("hamster"); + list.append("snake"); + list.append("turtle"); + ``` + +1. Add `console.log(list.toString());` to the end of the file and run it. +1. If everything is working, the output should be: + + ```text + ( dog ) -> ( cat ) -> ( parrot ) -> ( hamster ) -> ( snake ) -> ( turtle ) -> null + ``` + + Feel free to use different values to test if you like. + diff --git a/javascript/computer_science/project_recursion.md b/javascript/computer_science/project_recursion.md index ce849807212..0cbc02ad801 100644 --- a/javascript/computer_science/project_recursion.md +++ b/javascript/computer_science/project_recursion.md @@ -43,7 +43,7 @@ First up create a file and tackle the fibonacci sequence: 1. Now write another function `fibsRec` which solves the same problem recursively. 1. Test both versions of your functions by passing in various lengths as arguments. -Hopefully you were able to solve the problem with recursion! If you need some help understanding what's going on with this function, there are some additional resources linked at the end of this page. +Hopefully you were able to solve the problem with recursion! If you need some help understanding what's going on with this function, the "Test it out" section below will help. If you're still a bit confused, there are some additional resources linked at the end of this page. Once you have a firm grasp on solving Fibonacci with recursion, create a new file and work on a merge sort: @@ -54,6 +54,19 @@ Tips: - Think about what the base case is and what behavior is happening again and again and can actually be delegated to someone else (e.g. that same function!). - It may be helpful to check out the background videos again if you don't quite understand what should be going on. +#### Test it out + +To showcase the recursive effect implemented in your Fibonacci function, do the following: + +1. Add the following to the start of the function: + + ```javascript + console.log("This was printed recursively"); + ``` + +1. Call the function with `8` as the argument. +1. If the function is implemented correctly, you should see that sentence printed around 8 times (keep in mind that, depending on the way you implemented the function, you may see 7 instead of 8. This isn't a bug! It simply depends on how many times the function is *actually* repeated). + ### Additional resources diff --git a/javascript/computer_science/recursive_methods.md b/javascript/computer_science/recursive_methods.md index 1acffcf8169..5e4d2d1243f 100644 --- a/javascript/computer_science/recursive_methods.md +++ b/javascript/computer_science/recursive_methods.md @@ -32,7 +32,7 @@ This section contains a general overview of topics that you will learn in this l -### Test yourself +#### Test yourself
@@ -40,7 +40,7 @@ This section contains a general overview of topics that you will learn in this l
-The solution for "Question 6: Search JS object" is incorrect. See the [corrected solution](https://gist.github.com/JoshDevHub/b00125f483d4a1ecc257eaa030916973) after you solve it. +The solution for "Question 6: Search JS object" is incomplete. See [a more accurate solution for `contains()`](https://gist.github.com/JoshDevHub/b00125f483d4a1ecc257eaa030916973) after you solve it.
diff --git a/javascript/computer_science/time_complexity.md b/javascript/computer_science/time_complexity.md index 9a4993de6af..08d3d3fd3ab 100644 --- a/javascript/computer_science/time_complexity.md +++ b/javascript/computer_science/time_complexity.md @@ -325,7 +325,7 @@ The following questions are an opportunity to reflect on key topics in this less - [What is Big O?](#what-is-big-o) - [What are the Big O Notations?](#big-o-notation) - [Why use Big O?](#why-big-o) -- [What is Big Omega and why isn't it as useful?](#big--omega-notation) +- [What is Big Omega and why isn't it as useful?](#big-omega-notation) ### Additional resources diff --git a/javascript/javascript_in_the_real_world/dynamic_user_interface_interactions.md b/javascript/javascript_in_the_real_world/dynamic_user_interface_interactions.md index 7db2b9f6a45..a38fa3c5e58 100644 --- a/javascript/javascript_in_the_real_world/dynamic_user_interface_interactions.md +++ b/javascript/javascript_in_the_real_world/dynamic_user_interface_interactions.md @@ -19,7 +19,7 @@ A dropdown is something you've most likely encountered on various other websites Dropdowns are typically comprised of two main parts: 1. A button that toggles the dropdown content's visibility. -1. The dropdown contents itself. +1. The dropdown content itself. The dropdown toggle button should typically only trigger the visibility of the dropdown content on click, while the dropdown contents should typically only contain items that will trigger an action upon clicking them. Actions can include things like "Edit", "Copy", or "Delete", or linking you to another part of the site, such as in a navbar. @@ -46,7 +46,7 @@ Create an image carousel. It should contain arrows on each side to advance the i Don't spend too much time worrying about getting your images to display at the correct size -- it's more important to get the carousel rotating. -1. This one is a little more involved than the last two, so think about how you would set up the different elements within the site. +1. This one is a little more involved than the previous task, so think about how you would set up the different elements within the site. 1. Set up a very wide `div` which will contain the individual "slides" of each image. By appropriately positioning that `div` inside a container `div` (which acts like a picture frame), you can choose which slide is visible at any given time. 1. Once you have the slider positioned properly, build functions for "next" and "previous" which will advance to the next or previous slide accordingly. The transition *doesn't* need to be smooth or animated. Only make it switch to the correct slide. 1. Set up arrow buttons which activate those functions and play with cycling through the images. diff --git a/javascript/javascript_in_the_real_world/linting.md b/javascript/javascript_in_the_real_world/linting.md index 360e709a948..7a25c75d65d 100644 --- a/javascript/javascript_in_the_real_world/linting.md +++ b/javascript/javascript_in_the_real_world/linting.md @@ -1,6 +1,6 @@ ### Introduction -Before we dive all the way into the Code, we are going to take a moment to improve your editor setup and overall productivity. Doing this now will make things much easier for you going forward. This lesson will give you some information about code style, and then give you some tools to help you maintain consistent code-style throughout your projects. In some cases it can even help adjust things like indentation for you! We will also introduce template repositories which can save you time setting up projects that share a lot of configuration with other projects. +Before we dive further into code, we are going to take a moment to improve your editor setup and overall productivity. Doing this now will make things much easier for you going forward. This lesson will give you some information about code style, and then give you some tools to help you maintain consistent code-style throughout your projects. In some cases it can even help adjust things like indentation for you! ### Lesson overview @@ -8,11 +8,10 @@ This section contains a general overview of topics that you will learn in this l - Learn about style guides and why they are important. - Set up a linter and prettier to make your code better. -- Learn what template repositories are and how to set one up. ### Style guides -Code style is important! Having a consistent set of style rules for things such as indentation or preferred quote style makes your code more maintainable and easier to read. There are several popular JavaScript style guides on the net that set standards for these types of things, and a little time spent reading them *will* make you a better developer. +Code style is important! Having a consistent set of style rules for things such as indentation or preferred quote style makes your code more maintainable and easier to read. There are several popular JavaScript style guides on the net that set standards for these types of things, and a little time spent looking through them them *will* make you a better developer. Have a little look at some popular style guides for an idea of what sort of things can be done to improve consistency: 1. The [Airbnb Style Guide](https://github.com/airbnb/javascript) is one of the most popular. It is also very well formatted and easy to read. 1. There is also a [JavaScript style guide used at Google](https://google.github.io/styleguide/jsguide.html). @@ -20,47 +19,48 @@ Code style is important! Having a consistent set of style rules for things such ### Linting -The style guides we mentioned above are full of really helpful advice for formatting, organizing and composing your code. But there are a *lot* of rules - it can be difficult to internalize them all. **Linters** are tools that will scan your code with a set of style rules and will report any errors to you that they find. In some cases, they can even auto-fix the errors! The following articles explain in more detail the benefits of using a linter while you code. - -1. This article on [JavaScript linters](https://gomakethings.com/javascript-linters/) gets right to the point... start here! -1. Read this article that goes a little further by discussing exactly [*how* linters do what they do](https://hackernoon.com/how-linting-and-eslint-improve-code-quality-fa83d2469efe). +The style guides we mentioned above are full of really helpful advice for formatting, organizing and composing your code. But there are a *lot* of rules - it can be difficult to internalize them all. **Linters** are tools that will scan your code with a set of style rules and will report any errors to you that they find. In some cases, they can even auto-fix the errors! There are multiple options for linting your JavaScript, but the most popular (and most common in the industry) is [ESLint](https://eslint.org/). Getting it installed and the initial set-up is straightforward. -1. [The official 'Getting Started' page](https://eslint.org/docs/user-guide/getting-started) is a good place to start. It covers installation and basic setup. The basic way to use this tool is to run the `eslint` command in your terminal with a specific file. +1. [ESLint's official 'Getting Started' page](https://eslint.org/docs/user-guide/getting-started) is a good place to start. It covers installation and basic setup. The basic way to use this tool is to run the `eslint` command in your terminal with a specific file. - You may also want to look at the [docs on configuring ESLint](https://eslint.org/docs/latest/use/configure/) for a list of options that you can change. +1. There is an [ESLint extension for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) with which you can get automatic lint highlighting for your files as you write, without you needing to rerun the `eslint` command every time. If your open workspace also contains an ESLint configuration file at the top level, the extension will automatically use those rules for that project. -1. There is an [ESLint extension for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) with which you can get automatic lint highlighting for your files as you write, without you needing to rerun the `eslint` command every time. If your project also contains an ESLint configuration file, the extension will automatically use those rules for that project. +
-
+#### ESLint v9 and flat config support -#### A note if your ESLint config is not loading +The above ESLint doc links take you to the docs for v9, which was released in April 2024. v9 came with a lot of big changes, including forcing all ESLint config files to use the "flat config" format (`eslint.config.(m|c)js`). + +Because of these changes, some community plugins like [eslint-config-airbnb-base](https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb-base) (which makes ESLint use Airbnb's ruleset) have not yet been able to release a version that supports v9 or flat config. -The current version of the extension (2.4.4) will only pick up the workspace folder's ESLint config file, and not a config file for a subdirectory of that workspace. Switching to the pre-release version solves this. You will also need to enable `Eslint: Use Flat Config` in VSCode's settings. +For the time being, if you wish to use airbnb's style guide with ESLint, you will need to use [ESLint's v8.57 version of the docs](https://eslint.org/docs/v8.x/use/getting-started) and make sure you use one of the older [eslintrc configuration file formats](https://eslint.org/docs/v8.x/use/configure/configuration-files), **not** the newer flat config format.
-
+### Formatters -#### ESLint v9 and flat config support +Formatters are *awesome*. They are similar to linters, but serve a slightly different function. Formatters take your JavaScript code and then automatically format it according to a set of rules. Unlike linters, they do not look for style errors, but specifically target the layout of your code, making intelligent decisions about things like spaces, indentation levels and line-breaks. -The above ESLint doc links take you to the docs for v9, which was released in April 2024. v9 came with a lot of big changes, including forcing all ESLint config files to use the "flat config" format (`eslint.config.(m|c)js`). +As usual, there are multiple formatters out there. [Prettier](https://prettier.io/) is a very popular choice that is highly opinionated. Besides a few options, most of its formatting decisions are not customizable. Since many of these decisions have been made for you, this reduces the time spent deciding on things like indentation size or spacing, and more time on the problems that actually matter. -Because of these changes, some community plugins like [eslint-config-airbnb-base](https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb-base) (which makes ESLint use airbnb's ruleset) have not yet been able to release a version that supports v9 or flat config. +1. Read [Prettier's installation guide](https://prettier.io/docs/en/install.html) for installing it as a dependency in your projects. +1. Prettier also has [instructions for setting up and configuring the VSCode Prettier extension](https://github.com/prettier/prettier-vscode). This extension allows you to format with Prettier via Visual Studio Code commands or keybinds instead of commands in the terminal. -For the time being, if you wish to use airbnb's style guide with ESLint, you will need to use [ESLint's v8.57 version of the docs](https://eslint.org/docs/v8.x/use/getting-started) and make sure you use one of the older [eslintrc configuration file formats](https://eslint.org/docs/v8.x/use/configure/configuration-files), **not** the newer flat config format. +Using Prettier makes coding faster and easier! You don't have to worry about nailing things like indentation, or remembering every semi-colon because prettier will take care of those details for you. -
+
-### Prettier +#### Extensions and project dependencies -Prettier is *awesome*. It is similar to a linter, but serves a slightly different function. Prettier will take your JS code and then automatically format it according to a set of rules. Unlike a linter, it's not looking for style errors, but specifically targeting the layout of your code and making intelligent decisions about things like spaces, indentation levels and line-breaks. +While the Visual Studio Code extensions for ESLint and Prettier are really convenient, they are local to your machine only. It's good practice to install any linters and formatters as dev dependencies in your projects as well. -1. Watch this [short intro to Prettier](https://www.youtube.com/watch?v=hkfBvpEfWdA) by its creator. -1. Go to [Prettier's online playground](https://prettier.io/playground) and give it a test drive. Go ahead and copy/paste some of your old JavaScript code into that editor and see what happens. -1. Prettier has [instructions for setting up and configuring the VSCode Prettier extension](https://github.com/prettier/prettier-vscode). +At some point, you may need to work on code with multiple people, and others may not use all of the same tools as you. Therefore, including linters and formatters as dependencies in your project, as well as any rule configuration files, allows everyone access to the same linting and formatting tools and rules. -Using prettier makes coding faster and easier! You don't have to worry about nailing things like indentation, or remembering every semi-colon because prettier will take care of those details for you. +Editor extensions can then be used to make linting and formatting more convenient for you. The ESLint and Prettier extensions will recognise and use any rule files in your project. If your open workspace has ESLint installed as a dependency, then the ESLint extension can automatically detect this to apply the right setting for whether to use the flat config or legacy eslintrc format. + +
### Using ESLint and Prettier @@ -70,22 +70,33 @@ For most people using the default ESLint ruleset, there will be no special setup Some community plugins, such as [eslint-config-airbnb-base](https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb-base), turn on some stylistic rules that may clash with what Prettier formats. If you wish to use a plugin like `eslint-config-airbnb-base` and Prettier together, you will also need to install [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) which will turn off any of the ESLint rules that clash with Prettier. If you are using the default ESLint ruleset, you will not need this. -### Template repositories +
+ +#### Adding setup to template repositories -With the last few projects, you might have felt that setting up Webpack involved a fair few files and configuration, and that you may have had to look at what you configured before to copy and paste the configuration you want to reuse. You may also have noticed that whenever you create a new repository on Github, there is an option near the top for a `Repository template`. +Recall [template repositories](https://www.theodinproject.com/lessons/node-path-javascript-revisiting-webpack#template-repositories)? You can include linter and formatter setup in any of your templates to make things quicker and easier in the future! -This is where template repositories can come very much in handy. Any of your existing repositories can be converted to a template in its settings (right under where you can rename the repository, there is a checkbox for whether the repository is a template or not). If you check this box, congratulations, that's all you need to do! Now when you go to create a new repository, the `Repository template` dropdown will have any templates listed for you to select. Selecting one will mean your new repository will be a copy of the chosen template, not an empty one! +
-If you find yourself reusing a lot of setup code for multiple projects, you can make a new repository with all of the setup code you need then mark it as a template. Now you can select that template when creating a new project repository to save time getting set up, letting you dive into working on the project itself sooner! +### Assignment + +
+ +1. Read this article that goes more into [the value of linters and how they work](https://hackernoon.com/how-linting-and-eslint-improve-code-quality-fa83d2469efe). +1. Watch this [short intro to Prettier](https://www.youtube.com/watch?v=hkfBvpEfWdA) by its creator. +1. Go to [Prettier's online playground](https://prettier.io/playground) and give it a test drive. Go ahead and copy/paste some of your old JavaScript code into that editor and see what happens. + +
### Knowledge check The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. -- [What is linting?](https://gomakethings.com/javascript-linters/) -- [Which problems can linting prevent?](https://gomakethings.com/javascript-linters/) -- [Why should you use Prettier?](https://www.youtube.com/watch?v=hkfBvpEfWdA) -- [What is a template repository?](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-template-repository) +- [What is linting?](#linting) +- [Which problems can linting prevent?](https://hackernoon.com/how-linting-and-eslint-improve-code-quality-fa83d2469efe) +- [What are some of the benefits of using a formatter?](#formatters) +- [What is Prettier?](https://www.youtube.com/watch?v=hkfBvpEfWdA) +- [Why should you install linters and/or formatters as dev dependencies in your project?](#extensions-and-project-dependencies) ### Additional resources diff --git a/javascript/organizing_your_javascript_code/classes.md b/javascript/organizing_your_javascript_code/classes.md index 82c6a8cd90f..f9838bf1520 100644 --- a/javascript/organizing_your_javascript_code/classes.md +++ b/javascript/organizing_your_javascript_code/classes.md @@ -15,8 +15,8 @@ This section contains a general overview of topics that you will learn in this l - Explain the differences between an object constructor and a class. - Explain what "getters" and "setters" are. - Understand what computed names and class fields are. -- Explain how to implement private class fields and methods. - Describe function binding. +- Explain how to implement private class fields and methods. - Use inheritance with classes. - Understand why composition is generally preferred to inheritance. @@ -24,15 +24,13 @@ This section contains a general overview of topics that you will learn in this l
-1. [JavaScript.info's article on Getters and Setters](https://javascript.info/property-accessors) should get you up to speed on "Getters and Setters". - -1. [JavaScript.info's primer on class syntax](https://javascript.info/class) is probably just about all you need to start using `class` syntax confidently. - -1. [MDN's docs on classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) are, as usual, a great resource for going a little deeper. Look especially at the ['extends' reference page](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends), including the ['Mixins' section](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends#mix-ins). In some frameworks like React, you can use classes to create your components and make them `extend` the core React component which gives you access to all their built-in functionality (though this is not the only way to create components. This will all be covered later in React section of the course). Classes can also have [private class properties](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields) that allow you to implement privacy similarly to factory functions. - -1. Classes can have [static properties and methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static) which are properties and methods that are accessed on the class itself and not on the instance of a class. This is similar to how some string methods are accessed on the instance of a string itself e.g. `someString.slice(0, 5)` whereas some methods are called on the String constructor directly e.g. `String.fromCharCode(79, 100, 105, 110)`. - -1. Read this article covering [opinions regarding the pros and cons of classes](https://medium.com/@rajaraodv/is-class-in-es6-the-new-bad-part-6c4e6fe1ee65). [FunFunFunction's video on Composition over Inheritance](https://www.youtube.com/watch?v=wfMtDGfHWpA) elaborates on the cons mentioned in the article and does a great job of going over the topic. +1. Read this article covering [opinions regarding the pros and cons of classes](https://medium.com/@rajaraodv/is-class-in-es6-the-new-bad-part-6c4e6fe1ee65). +1. [JavaScript.info's article on Getters and Setters](https://javascript.info/property-accessors) should get you up to speed on "Getters and Setters", and [JavaScript.info's primer on class syntax](https://javascript.info/class) is probably just about all you need to start using `class` syntax confidently. +1. [MDN's docs on classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) are, as usual, a great resource for going a little deeper. + - Take a look at the ['extends' documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends), including the ['Mixins' section](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends#mix-ins). In some frameworks like React, you can use classes to create your components and make them `extend` the core React component which gives you access to all their built-in functionality (though this is not the only way to create components. This will all be covered later in the React section of the course). + - Classes can also have [private class properties](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields) that allow you to implement privacy similarly to factory functions. + - Classes can have [static properties and methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static) which are properties and methods that are accessed on the class itself and not on the instance of a class. This is similar to how some string methods are accessed on the instance of a string itself e.g. `someString.slice(0, 5)` whereas some methods are called on the String constructor directly e.g. `String.fromCharCode(79, 100, 105, 110)`. +1. [FunFunFunction's video on Composition over Inheritance](https://www.youtube.com/watch?v=wfMtDGfHWpA) gives a great overview of the topic.
@@ -44,14 +42,14 @@ Go back to your [Library project](https://www.theodinproject.com/lessons/node-pa The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. -- [Describe the pros and cons of using classes in JavaScript.](https://rajaraodv.medium.com/is-class-in-es6-the-new-bad-part-6c4e6fe1ee65) +- [What are some of the pros and cons of using classes in JavaScript?](https://rajaraodv.medium.com/is-class-in-es6-the-new-bad-part-6c4e6fe1ee65) - [How does JavaScript's object creation differ from other object-oriented programming languages?](https://rajaraodv.medium.com/is-class-in-es6-the-new-bad-part-6c4e6fe1ee65#e6b3) -- [Explain the differences between object constructors and classes.](https://javascript.info/class#not-just-a-syntactic-sugar) +- [What differences are there between object constructors and classes?](https://javascript.info/class#not-just-a-syntactic-sugar) - [What are "getters" & "setters"?](https://javascript.info/property-accessors) -- [Describe computed names and class fields.](https://javascript.info/class) -- [Describe function binding.](https://javascript.info/class) -- [Describe static properties.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static) -- [Describe private class features.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields) +- [What are computed names and class fields?](https://javascript.info/class) +- [What is function binding?](https://javascript.info/class) +- [What are static properties?](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static) +- [What are some private class features?](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields) - [How is inheritance used with classes?](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#inheritance) - [Why is favoring Composition over Inheritance suggested?](https://www.youtube.com/watch?v=wfMtDGfHWpA) @@ -60,5 +58,4 @@ The following questions are an opportunity to reflect on key topics in this less This section contains helpful links to related content. It isn't required, so consider it supplemental. - Stephen Mayeux has a [Youtube playlist on ES6 classes](https://www.youtube.com/playlist?list=PLtwj5TTsiP7uTKfTQbcmb59mWXosLP_7S) and some of their methods with easy to follow examples. - - Here are some more examples that try to illustrate the [benefits of composition over inheritance](https://blog.beezwax.net/composition-over-inheritance-with-javascript-examples). diff --git a/javascript/organizing_your_javascript_code/es6_modules.md b/javascript/organizing_your_javascript_code/es6_modules.md index cc3f3d36a8d..3049ee31db5 100644 --- a/javascript/organizing_your_javascript_code/es6_modules.md +++ b/javascript/organizing_your_javascript_code/es6_modules.md @@ -1,183 +1,249 @@ ### Introduction -Separate from the **module pattern** that we discussed in an earlier lesson, "modules" is a feature that arrived with ES6. ES6 modules are starting to appear in many code bases around the net and getting them up and running will give us a chance to explore some new parts of the JavaScript ecosystem, so it's going to be a worthy excursion! +We've learned about the **module pattern** in a previous lesson and played around with using them to help organize our variables and functions. At some point in the last few projects, you may have even wondered, "How would we manage more complex projects? Files would get too long! It would be great if we could split our code up into multiple files for organization!". Using multiple files would be extremely handy for this exact reason. -Don't be fooled! We're going to cover much more than just the new module syntax in this lesson! Before we can really *use* these modules, we're going to have to learn about **npm** and **webpack**, which are both topics that will be *very* useful to you even beyond this lesson. In the end, the modules themselves are simple to implement, so we're going to take this chance to learn about a few other things. +While the module pattern used to play a big part in helping us manage this, the release of ES6 (sometimes referred to as ES2015) gave us actual "modules" and thus they are often referred to as "ES6 modules" or "ESM". ### Lesson overview This section contains a general overview of topics that you will learn in this lesson. -- Explain what npm is and where it was commonly used before being adopted on the frontend. -- Describe what `npm init` does and what `package.json` is. -- Know how to install packages using npm. -- Describe what a JavaScript module bundler like webpack is. -- Explain what the concepts "entry" and "output" mean in relation to webpack. -- Briefly explain what a development dependency is. -- Explain what "transpiling code" means and how it relates to front-end development. -- Briefly describe what a task runner is and how it's used in front-end development. -- Describe how to write an npm automation script. -- Explain one of the main benefits of writing code in modules. -- Explain "named" exports and "default" exports. +- Explain what ES6 modules are and how to import and export from them. +- Describe the difference between default and named exports. +- Explain the main differences between CommonJS modules and ES6 modules. -### The history of JavaScript +### Before ES6 modules: The global scope problem -Why do we even need or want this stuff? What do you gain from all of this added complexity? These are good questions... with good answers. +
-- Read this little [history lesson on JavaScript, package managers, and bundling](https://peterxjang.com/blog/modern-javascript-explained-for-dinosaurs.html). It's long, but it puts what we're doing here in great perspective. This article is a bit older, and those who have coded along with the example have frequently run into issues, so we don't suggest that you code along (you'll be following along with the official Webpack documentation later). Nevertheless, this article is extremely important conceptually and really clarifies the 'WHY' of the rest of this lesson. +Even though `let`/`const` and arrow functions were not around before ES6, we will still use them in our pre-ES6 examples. They won't change how things work regarding the global scope and the module pattern, which is the main focus of this section. -### npm +
-The **node package manager** is a command-line tool that gives you access to a gigantic repository of plugins, libraries and tools. If you have done our Fundamentals course, you will probably have encountered it when you [installed the Jest testing framework](https://github.com/TheOdinProject/javascript-exercises#how-to-use-these-exercises) to do our exercises. +Let's say we have two scripts, `one.js` and `two.js`, and we link them in our HTML as separate scripts. -Read through the npm links below but don't worry about running any of the commands on your computer. This section is about growing your awareness of npm. You will have an opportunity to use what you learn here in upcoming projects. +```html + + +``` + +```javascript +// one.js +const greeting = "Hello, Odinite!"; +``` + +```javascript +// two.js +console.log(greeting); +``` + +When we open the HTML, we see `"Hello, Odinite!"` getting logged to the console, even though `greeting` was never defined in `two.js`! That's because the two scripts were loaded one after the other into the same global scope, as if we wrote only one file with the two lines in that order. If we put the `two.js` script tag first, we would instead get an error that `greeting is not defined`, as it would try to do the console log before we define the variable. -1. Take a couple minutes to read the [About npm](https://docs.npmjs.com/getting-started/what-is-npm) page - a great introduction to npm. -1. This tutorial teaches you [how to install packages with npm](https://docs.npmjs.com/downloading-and-installing-packages-locally). -1. This tutorial covers [the `package.json` file](https://docs.npmjs.com/creating-a-package-json-file), which you can use to manage your project's dependencies. -1. Read this article on [development dependencies](https://dev.to/moimikey/demystifying-devdependencies-and-dependencies-5ege) to learn what they are and how to use them. Note that when the author says "all required dependencies are pulled together and bundled", they are referring to any dependencies needed at runtime. Dependencies like Webpack (which we will cover shortly) are only used during development to build apps and so are not required at runtime. -1. If you run into trouble at any point you can check out [the official npm docs](https://docs.npmjs.com/) for more tutorials and documentation. +This means that even if we use multiple JavaScript files, they will still end up sharing the same global scope. Our top-level variables are not safe! -### Yarn? +Before ESM, we could wrap some things in an IIFE, which would cause it to run just the same, but now any variables inside them are scoped to that function and not globally. -At some point, you will probably run into [Yarn](https://yarnpkg.com/en/) - a replacement for the default `npm`. For the most part, it does the same things, though it *does* have a few more features. Recent versions of `npm` have incorporated some of the best features of Yarn, so using it won't offer you any real advantages at this point in your career. It *is* a fine package manager, however, and may be worth your consideration in the future. +```javascript +// one.js +(() => { + const greeting = "Hello, Odinite!"; +})(); +``` -### Webpack and bundlers +Now, we get an error in the console that `greeting is not defined`, because there is no global variable called `greeting` for us to log! But what if we wanted only *some* things to be exposed to other files? We can return those things from our IIFE into the global scope and keep the other things private! -So far, your projects have had relatively basic file structures. As project complexity grows, so too will the benefits of well-organized code. A project consisting of a single, long file with lots of code can be made easier to navigate and maintain by being broken down into multiple smaller files (modules). Further benefits of writing code in modules will come below when we introduce ES6 modules. +```javascript +// one.js +const greeting = (() => { + const greetingString = "Hello, Odinite!"; + const farewellString = "Bye bye, Odinite!"; + return greetingString; +})(); +``` -But there's a problem! The browser would need to make a separate HTTP request for each file. The more files you have, the more costly this becomes, particularly on slower networks and would only increase if you also imported third-party libraries into your app. +Now, the global variable `greeting` will contain `"Hello, Odinite!"` and so our code from `two.js` successfully logs this to the console. However, our private `farewellString` variable is not global, so that cannot be accessed anywhere in `two.js`. Through this, we are able to choose what to expose from one file to be made available to all files that follow it! This is why IIFEs were often called the "module pattern", because they allowed us to write modular code across multiple files before we were given "real modules". -What if we had a way to write multiple files and/or import multiple third-party libraries but eventually combine them all into fewer files at the end so the browser did not have to make so many requests? +But now, with ESM, we no longer need to use IIFEs for this specific purpose. -Enter bundlers. Give a bundler a starting file (an entry point) and it will build a dependency graph of the modules and dependencies starting from that file, then combine them into a single output file. Provide multiple entry points and it will do the same for each separately. You can read more about [why we use bundlers and how they work](https://snipcart.com/blog/javascript-module-bundler) in this short article. +### ES6 modules -Webpack is one such tool for bundling modules. There is a lot of talk across the net about how difficult and complex it is to set up and use, but at the moment our needs are few and the setup is basic enough. In fact, you can see an example of getting it up and running on the [front page of the Webpack website](https://webpack.js.org/). +With ESM, we have a little more control over things. Each file has its own private scope by default, and not only can we choose what things we export from that file, we can also choose what things we import into other files. So just because we export something, it doesn't mean it's automatically available elsewhere; it will only be available in another file if we explicitly import it there. Lots of control! -Webpack *is* a very powerful tool, and with that power comes a decent amount of complexity. Don't let it scare you off! The basic configuration is not difficult and proficiency with webpack looks *amazing* on resumes. +
-To get us started, we are going to refer to the official documentation. +#### Module scope is not the global scope -1. Code along with all of the steps of [Webpack's "Getting Started" tutorial](https://webpack.js.org/guides/getting-started/). +When using ESM, each module has its own private scope, where we use import/export to communicate between files. A top-level variable in a module will not be accessible in the global scope. -Let's discuss what's going on there. After installing webpack using npm, we set up a project that required an external library ([Lodash](https://lodash.com/)) using a ` +``` + +Why is `two.js` our entry point? Well, in our above examples, `two.js` imports variables from `one.js`, meaning `two.js` depends on `one.js`, so we have the following **dependency graph**: + +```text +importer depends on exporter +two.js <-------------- one.js +``` + +When we load `two.js` as a module, the browser will see that it depends on `one.js` and load the code from that file as well. If we instead used `one.js` as our entry point, the browser would see that it does not depend on any other files, and so would do nothing else. Our code from `two.js` would not be used, and nothing would get logged! + +If we had another file, `three.js`, that exported something and `two.js` imported from it, then `two.js` would still be our entry point, now depending on both `one.js` and `three.js`. + +```text +two.js <-------------- one.js + └------- three.js +``` + +Or perhaps instead of `two.js`, `one.js` imports from `three.js`. In which case, `two.js` would still be our entry point and depend on `three.js` indirectly through `one.js`. + +```text +two.js <-------------- one.js <-------------- three.js ``` -Using this pattern gives you the freedom to only import the functions you need in the various files of your program. So it's perfectly fine to only import `functionOne` if that's the only one you need. +Note that we only needed the one script tag, as the browser will handle the additional file dependencies for us. We also did not need to add the `defer` attribute, as `type="module"` will automatically defer script execution for us. + +If you had coded along with the IIFE example at the start of the lesson, try rewriting the JavaScript to use `import` and `export`, and link only the entry point as a module script. + +### CommonJS + +Along the way, you may have bumped into something called CommonJS (CJS), which uses syntax like `require` and `module.exports` instead of `import` and `export`. You may remember seeing this in our JavaScript exercises in the Foundations course (you've come a long way)! This is a module system that was designed for use with Node.js that works a little differently than ESM, and is not something that browsers will be able to understand. + +CJS is still used quite a lot in Node.js code, though in recent years, ESM in Node.js has been gaining popularity. For the time being, we are focused on writing code to run in the browser, so we will be spending time with ESM. If you are taking the Full Stack JavaScript pathway, then we will cover CJS in more detail later in the Node.js course. + +### Assignment + +
+ +1. As per usual, you can learn most about JavaScript keywords and concepts from the MDN docs, so check out the [docs on export](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) and [docs on import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import). There are little extras about them we have not covered in this lesson, such as aliases and namespace imports. + +
### Knowledge check The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. -- [Explain what npm is and where it was commonly used before being adopted on the frontend.](https://peterxjang.com/blog/modern-javascript-explained-for-dinosaurs.html) -- [Describe what `npm init` does and what `package.json` is.](https://docs.npmjs.com/creating-a-package-json-file) -- [Know how to install packages using npm.](https://docs.npmjs.com/downloading-and-installing-packages-locally) -- [Describe what a JavaScript module bundler like webpack is.](https://peterxjang.com/blog/modern-javascript-explained-for-dinosaurs.html) -- [Explain what the concepts "entry" and "output" mean in relation to webpack.](#webpack-knowledge-check) -- [Briefly explain what a development dependency is.](https://dev.to/moimikey/demystifying-devdependencies-and-dependencies-5ege) -- [Explain what "transpiling code" means and how it relates to frontend development.](https://peterxjang.com/blog/modern-javascript-explained-for-dinosaurs.html) -- [Briefly describe what a task runner is and how it's used in frontend development.](https://peterxjang.com/blog/modern-javascript-explained-for-dinosaurs.html) -- [Describe how to write an npm automation script.](https://peterxjang.com/blog/modern-javascript-explained-for-dinosaurs.html) -- [Explain one of the main benefits of writing code in modules.](#module-knowledge-check) -- [Explain "named exports" and "default exports".](#exports-knowledge-check) +- [Before ES6 modules, how would you privatize a variable from being accessible in other files?](#before-es6-modules-the-global-scope-problem) +- [Before ES6 modules, how would you expose variables to be accessible in later files?](#before-es6-modules-the-global-scope-problem) +- [What are some benefits of writing code in modules?](#introduction) +- [What is the difference between default and named exports?](#default-exports) +- [What is an entry point?](#entry-points) +- [How do you link a module script in HTML?](#entry-points) ### Additional resources This section contains helpful links to related content. It isn't required, so consider it supplemental. -- Watch this video about [ES6 Modules by Web Dev Simplified](https://youtu.be/cRHQNNcYf6s) if you find video lessons easier to absorb. It covers the same topics as discussed in this lesson. -- Here is [a brief comparison of CommonJS modules and ES6 modules](https://blog.logrocket.com/commonjs-vs-es-modules-node-js/). +- This video on [ES6 Modules by Web Dev Simplified](https://youtu.be/cRHQNNcYf6s) summarizes much of the ESM topics discussed in this lesson. At the end, he mentions `nomodule` and support for older browsers that were unable to support ESM. Nowadays, this is not a concern as ESM is supported by basically every browser in common use. +- Here is a [brief comparison of CommonJS modules and ES6 modules](https://blog.logrocket.com/commonjs-vs-es-modules-node-js/). diff --git a/javascript/organizing_your_javascript_code/factory_functions_and_module_pattern.md b/javascript/organizing_your_javascript_code/factory_functions_and_module_pattern.md index b5c05481bb8..92541e04f69 100644 --- a/javascript/organizing_your_javascript_code/factory_functions_and_module_pattern.md +++ b/javascript/organizing_your_javascript_code/factory_functions_and_module_pattern.md @@ -82,7 +82,7 @@ Now, while it may sound good at first glance, you may already be raising your ey Functions in JavaScript form closures. A closure refers to the combination of a function and the **surrounding state** in which the function was declared. This surrounding state, also called its **lexical environment**, consists of any local variables that were in scope at the time the closure was made. Here, `add5` is a reference to the `resulting` function, created when the `makeAdding` function is executed, thus it has access to the lexical environment of the `resulting` function, which contains the `first` variable, making it available for use. -This is a **crucial** behavior of functions - allowing us to associate data with functions and manipulate that data anywhere outside of the enclosing function. If you're still confused, take a small detour to examine the [second question under the Knowledge check section](#knowledge-check) - no need to read the entire thing for now, anything from "Emulating private methods with closures" onward will be discussed later in this lesson. +This is a **crucial** behavior of functions - allowing us to associate data with functions and manipulate that data anywhere outside of the enclosing function. If you're still confused, read the [MDN documentation on Closures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#closure), but only the sections "Lexical scoping", "Closure" and "Practical closures". The other sections refer to concepts that will be discussed later in this lesson. ### So, what's wrong with constructors? @@ -224,7 +224,7 @@ function createPlayer (name, level) { } ``` -### The module pattern - IIFEs +### The module pattern: IIFEs
@@ -274,14 +274,14 @@ Take the calculator example into consideration. It's very easy to imagine a scen The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. -- [Explain how scope works in JavaScript.](https://wesbos.com/javascript-scoping) -- [Explain what closures are and how they help in creating private variables.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#closure) -- [Describe the common issues that you can face when working with constructors.](#so-whats-wrong-with-constructors) -- [Describe private variables in factory functions and how they can be useful.](#private-variables-and-functions) -- [Describe how we can implement prototypal inheritance with factory functions.](#prototypal-inheritance-with-factories) -- [Explain how the module pattern works.](https://dev.to/tomekbuszewski/module-pattern-in-javascript-56jm) -- [Describe IIFEs and what they stand for.](http://adripofjavascript.com/blog/drips/an-introduction-to-iffes-immediately-invoked-function-expressions.html) -- [Explain the concept of namespacing and how factory functions help with encapsulation.](#encapsulating-with-the-module-pattern) +- [How does scope work in JavaScript?](#scoopfuls-of-scopes) +- [What are closures and how do they help in creating private variables?](#closures-arent-scary) +- [What common issues can you can face when working with constructors?](#so-whats-wrong-with-constructors) +- [What are private variables in factory functions and how can they be useful?](#private-variables-and-functions) +- [How can we implement prototypal inheritance with factory functions?](#prototypal-inheritance-with-factories) +- [How does the module pattern work?](https://dev.to/tomekbuszewski/module-pattern-in-javascript-56jm) +- [What does IIFE stand for and what are they?](#the-module-pattern-iifes) +- [What is the concept of namespacing and how do factory functions help with encapsulation?](#encapsulating-with-the-module-pattern) ### Additional resources diff --git a/javascript/organizing_your_javascript_code/npm.md b/javascript/organizing_your_javascript_code/npm.md new file mode 100644 index 00000000000..f85775b8d64 --- /dev/null +++ b/javascript/organizing_your_javascript_code/npm.md @@ -0,0 +1,73 @@ +### Introduction + +In the previous lesson, we learned about ES6 modules and the syntax used for importing and exporting things between modules. As we build bigger, more complex applications, we may not want to write *everything* ourselves. We may want to import third party code to handle some things for us, which can range from helper functions other people wrote, to entire frameworks for us to build our application within. To find and import these third party packages with ease, we need the help of a package manager such as npm! + +### Lesson overview + +This section contains a general overview of topics that you will learn in this lesson. + +- Understand what npm is. +- Understand the purpose of the `package.json` file. + +### npm + +**npm** (no capitals!) is a package manager - a gigantic repository of plugins, libraries, and other tools, which provides us with a command-line tool we can use to install these tools (that we call "packages") in our applications. We will then have all our installed packages' code locally, which we can import into our own files. We could even publish our own code to npm! + +You may recall installing npm in the Foundations course in order to install the Jest testing framework to do the JavaScript exercises. Funnily enough, [npm does not stand for "Node Package Manager"](https://www.npmjs.com/package/npm#is-npm-an-acronym-for-node-package-manager), though you will often see it referred to as such. + +If you are in the Full Stack Ruby on Rails pathway, you will have already been introduced to Yarn, another JavaScript package manager. For this course, we will be using npm. + +As our applications get more complex and more and more files are needed (whether they are our own files or files from packages we've installed and imported), managing many of these dependencies can become rather troublesome, especially when packages get updated. This can get even more troublesome when we consider that we may end up sending *many* JavaScript files to the browser to download. In the next lesson, we will introduce bundlers, tools that lets us write multiple files that are better for us to work with, then bundle them together into fewer smaller files which will ultimately be sent to the browser instead. + +### package.json + +npm revolves around a file called `package.json`. It's a JSON file containing information about our project, such as its name or any dependencies and their version numbers. npm can read this file and do things such as install all of the listed dependencies with the correct versions, and running commands that you've set as an npm script (we will cover npm scripts in a later lesson). + +For example, here is the `package.json` file for The Odin Project's curriculum repo that houses all of the lesson files (including this lesson you are doing right now): + +```json +{ + "name": "curriculum", + "version": "1.0.0", + "description": "[The Odin Project](https://www.theodinproject.com/) (TOP) is an open-source curriculum for learning full-stack web development. Our curriculum is divided into distinct courses, each covering the subject language in depth. Each course contains a listing of lessons interspersed with multiple projects. These projects give users the opportunity to practice what they are learning, thereby reinforcing and solidifying the theoretical knowledge learned in the lessons. Completed projects may then be included in the user's portfolio.", + "scripts": { + "lint:lesson": "markdownlint-cli2 --config lesson.markdownlint-cli2.jsonc", + "lint:project": "markdownlint-cli2 --config project.markdownlint-cli2.jsonc", + "fix:lesson": "markdownlint-cli2 --fix --config lesson.markdownlint-cli2.jsonc", + "fix:project": "markdownlint-cli2 --fix --config project.markdownlint-cli2.jsonc" + }, + "license": "CC BY-NC-SA 4.0", + "devDependencies": { + "markdownlint-cli2": "^0.12.1" + } +} +``` + +There's a lot of stuff here and we don't need to understand it all yet. The point is that if you were to clone the curriculum repo, if you ran `npm install`, npm would read this `package.json` file and see that it needs to install the `markdownlint-cli2` package. Once this package is installed, you'll be able to run any of the four npm scripts that use that package. The curriculum repo itself does not actually contain the code for the `markdownlint-cli2` package, as anyone cloning the repo can just run `npm install` to let npm grab the code for them. + +In our own projects, as we use npm to install new packages (or uninstall any!), it will automatically update our `package.json` with any new details. We will see this in action in the next lesson when we introduce module bundling using a package called Webpack. + +### Assignment + +
+ +1. Read a bit more about npm, packages, and dependencies: + 1. [Installing packages with npm](https://docs.npmjs.com/downloading-and-installing-packages-locally). + 1. Read about [the `package.json` file](https://docs.npmjs.com/creating-a-package-json-file), the file that stores much of the information for our application. + 1. Any packages we install are called "dependencies", but if any packages are only used during the development process and their code is not needed for the user-facing app (such as the Jest testing framework), we call them [development dependencies](https://dev.to/mshertzberg/demystifying-devdependencies-and-dependencies-5ege). +1. Here is a great little [history lesson about JavaScript and managing packages across multiple files](https://peterxjang.com/blog/modern-javascript-explained-for-dinosaurs.html). Only read up to "Using a JavaScript module bundler (webpack)", as we will cover bundlers and webpack in the next lesson. + +
+ +### Knowledge check + +The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. + +- [What is npm?](#npm) +- [What file does npm use that contains all information about dependencies?](https://docs.npmjs.com/creating-a-package-json-file) + +### Additional resources + +This section contains helpful links to related content. It isn't required, so consider it supplemental. + +- It looks like this lesson doesn't have any additional resources yet. Help us expand this section by contributing to our curriculum. diff --git a/javascript/organizing_your_javascript_code/objects_and_object_constructors.md b/javascript/organizing_your_javascript_code/objects_and_object_constructors.md index a9ec4962035..5ebcd9af129 100644 --- a/javascript/organizing_your_javascript_code/objects_and_object_constructors.md +++ b/javascript/organizing_your_javascript_code/objects_and_object_constructors.md @@ -358,7 +358,8 @@ If we had used `Object.setPrototypeOf()` in this example, then we could safely e 1. To go a bit deeper into both the chain and inheritance, spend some time with [JavaScript.Info's article on Prototypal Inheritance](http://javascript.info/prototype-inheritance). As usual, doing the exercises at the end will help cement this knowledge in your mind. Don't skip them! Important note: This article makes heavy use of `__proto__` which is not generally recommended. The concepts here are what we're looking for at the moment. We will soon learn another method or two for setting the prototype. 1. You might have noticed us using the `this` keyword in object constructors and prototype methods in the examples above. - 1. [Dmitri Pavlutin's article on the `this` keyword](https://dmitripavlutin.com/gentle-explanation-of-this-in-javascript/) is very comprehensive and covers how `this` changes in various situations. You should have a solid understanding of the concept after reading it. Pay special attention to the pitfalls mentioned in each section. + 1. [JavaScript Tutorial's article on the `this` keyword](https://www.javascripttutorial.net/javascript-this/) covers how `this` changes in various situations. Pay special attention to the pitfalls mentioned in each section. +1. Read the article [[[Prototype]] vs __proto__ vs .prototype in Javascript](https://medium.com/@eamonocallaghan/prototype-vs-proto-vs-prototype-in-javascript-6758cadcbae8)
@@ -366,22 +367,17 @@ If we had used `Object.setPrototypeOf()` in this example, then we could safely e The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. -- [Write an object constructor and instantiate the object.](#object-constructors) -- [Describe what a prototype is and how it can be used.](#the-prototype) -- [Explain prototypal inheritance.](https://javascript.info/prototype-inheritance) -- [Understand the basic do's and don't's of prototypal inheritance.](#recommended-method-for-prototypal-inheritance) -- [How does `this` behave in different situations?](https://dmitripavlutin.com/gentle-explanation-of-this-in-javascript/) +- [How do you write an object constructor and instantiate the object?](#object-constructors) +- [What is a prototype and how can it be used?](#the-prototype) +- [What is prototypal inheritance?](https://javascript.info/prototype-inheritance) +- [What are the basic do's and don't's of prototypal inheritance?](#recommended-method-for-prototypal-inheritance) +- [How does `this` behave in different situations?](https://www.javascripttutorial.net/javascript-this/) ### Additional resources This section contains helpful links to related content. It isn't required, so consider it supplemental. -- Lydia Hallie has a [visual article on prototypal inheritance](https://dev.to/lydiahallie/javascript-visualized-prototypal-inheritance-47co) and [prototype inheritance by Programming With Avelx](https://www.youtube.com/watch?v=sOrtAjyk4lQ) explains the Prototype concept with graphics and beginner friendly language. Try using these resources if you want another perspective to understand the concept. -- This [`Object.create` video by FunFunFunction](https://www.youtube.com/watch?v=CDFN1VatiJA) explains the method with great details about it, he walks through what it is, why `Object.create` exists in JavaScript, and how to use `Object.create`. Also you can check this [`Object.create` method video by techsith](https://www.youtube.com/watch?v=MACDGu96wrA) for another point of view on extending objects. -- [The Principles of Object-Oriented JavaScript](https://www.amazon.com/Principles-Object-Oriented-JavaScript-Nicholas-Zakas/dp/1593275404) book by -Nicholas C. Zakas is really great to understand OOP in JavaScript, which explains concepts in-depth, which explores JavaScript's object-oriented nature, revealing the language's unique implementation of inheritance and other key characteristics, it's not free but it's very valuable. +- This [`Object.create` method video by techsith](https://www.youtube.com/watch?v=MACDGu96wrA) provides another point of view on how to use `Object.create` to extend objects by setting the prototype. - The first answer on this StackOverflow question regarding [defining methods via the prototype vs in the constructor](https://stackoverflow.com/questions/9772307/declaring-javascript-object-method-in-constructor-function-vs-in-prototype/9772864#9772864) helps explain when you might want to use one over the other. -- [A Beginner’s Guide to JavaScript’s Prototype](https://medium.com/free-code-camp/a-beginners-guide-to-javascript-s-prototype-9c049fe7b34) and [JavaScript Inheritance and the Prototype Chain](https://medium.com/free-code-camp/javascript-inheritance-and-the-prototype-chain-d4298619bdae) from Tyler Mcginnis has great examples to help you understand Prototype and Prototype Chain better from the beginner's perspective. -- This video from Akshay Saini is an easy way to understand the [concept of Prototype, Prototype Chain and prototypal inheritance.](https://www.youtube.com/watch?v=wstwjQ1yqWQ). - [Interactive Scrim on objects and object constructors.](https://scrimba.com/scrim/co2624f87981575448091d5a2) - Check out this video explanation on the [`this` keyword from DevSage](https://www.youtube.com/watch?v=cwChC4BQF0Q) that gives a different perspective on how its context changes, as well as scenarios in which `this` behaves unexpectedly. diff --git a/javascript/organizing_your_javascript_code/oop_principles.md b/javascript/organizing_your_javascript_code/oop_principles.md index e7912c59f0b..851cd1eb871 100644 --- a/javascript/organizing_your_javascript_code/oop_principles.md +++ b/javascript/organizing_your_javascript_code/oop_principles.md @@ -67,8 +67,8 @@ This one is related pretty strongly to 'Single Responsibility' but takes a diffe
-1. The following article mentions the acronym **SOLID** before going on to talk about Single Responsibility. Single Responsibility is definitely the most relevant of the 5. Feel free to dig into the rest of the SOLID principles if you like, but pay special attention to Single Responsibility. - 1. [SOLID principle #1: Single responsibility (JavaScript)](https://duncan-mcardle.medium.com/solid-principle-1-single-responsibility-javascript-5d9ce2c6f4a5) has links to other very brief articles that cover the rest of 'SOLID'. They're optional, but recommended nonetheless. **Note**: this article riffs off what the SOLID videos in the next link goes in-depth on. +1. The following article and videos mention the acronym **SOLID** before going on to talk about Single Responsibility. Single Responsibility is definitely the most relevant of the 5, but feel free to dig into the rest of the SOLID principles, if you like. + 1. Read this article about [SOLID principle #1: Single responsibility (JavaScript)](https://duncan-mcardle.medium.com/solid-principle-1-single-responsibility-javascript-5d9ce2c6f4a5). It simplifies that which is covered in more detail in the SOLID videos below. 1. Watch [The SOLID Design Principles by WDS](https://www.youtube.com/playlist?list=PLZlA0Gpn_vH9kocFX7R7BAe_CvvOCO_p9) to see code examples for each principle. 1. [How to Write Highly Scalable and Maintainable JavaScript: Coupling](https://web.archive.org/web/20200810210808/https://medium.com/@alexcastrounis/how-to-write-highly-scalable-and-maintainable-javascript-coupling-c860787dbdd4) explains loosely coupled objects pretty well. @@ -78,16 +78,14 @@ This one is related pretty strongly to 'Single Responsibility' but takes a diffe The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. -- [Explain the "Single Responsibility Principle".](#single-responsibility) -- [Briefly explain the additional SOLID principles.](https://medium.com/@cramirez92/s-o-l-i-d-the-first-5-priciples-of-object-oriented-design-with-javascript-790f6ac9b9fa) -- [Explain what "tightly coupled" objects are and why we want to avoid them.](https://web.archive.org/web/20200810210808/https://medium.com/@alexcastrounis/how-to-write-highly-scalable-and-maintainable-javascript-coupling-c860787dbdd4) +- [What is the "Single Responsibility Principle"?](#single-responsibility) +- [What are the additional SOLID principles?](https://duncan-mcardle.medium.com/solid-principle-1-single-responsibility-javascript-5d9ce2c6f4a5) +- [What are "tightly coupled" objects and why do we want to avoid them?](https://web.archive.org/web/20200810210808/https://medium.com/@alexcastrounis/how-to-write-highly-scalable-and-maintainable-javascript-coupling-c860787dbdd4) ### Additional resources This section contains helpful links to related content. It isn't required, so consider it supplemental. - The best book we've ever read on the subject of loose coupling is [Practical Object-Oriented Design In Ruby](http://www.poodr.com/). Unfortunately, it is not free... and not JavaScript. We feel confident in recommending it anyway. If you don't know Ruby, it is a clear enough language that you don't really need to learn it to follow the examples and the content of the book is sincerely fantastic. Alternatively, [99 Bottles of OOP](https://sandimetz.com/products) is written in both JavaScript and Ruby. It is written by the same author and may be a better option if you are brand new to OOP (it is not free either). - - [Building a house from the inside out](https://www.ayweb.dev/blog/building-a-house-from-the-inside-out) will walk you through the process of separating your core logic and DOM logic. - - This [brief video by Coderized](https://www.youtube.com/watch?v=q1qKv5TBaOA) covers the SOLID programming principles and more, within the context of embracing clean coding practices and establishing a maintainable code structure. You may find it helpful if you are still confused about why these principles exist and how they can work together to improve your code, code architecture, and your skills as a programmer! diff --git a/javascript/organizing_your_javascript_code/project_restaurant_page.md b/javascript/organizing_your_javascript_code/project_restaurant_page.md index beaf4ada7eb..616a204e94f 100644 --- a/javascript/organizing_your_javascript_code/project_restaurant_page.md +++ b/javascript/organizing_your_javascript_code/project_restaurant_page.md @@ -8,11 +8,11 @@ Let's use what we've learned and take a chance to continue practicing DOM manipu #### .gitignore -When working with packages that are installed with npm, you don't need to track the contents of `node_modules` with git, nor push those files to GitHub. This is because the `package.json` file contains all the information, so that anyone can clone your project and install them on their machine with `npm install`. +When working with packages that are installed with npm, you don't need to track the contents of `node_modules` with git, nor push those files to GitHub. As we learned in the [npm lesson](https://www.theodinproject.com/lessons/node-path-javascript-npm), the `package.json` file contains all the dependency information, so that anyone can clone your project and install them on their machine with `npm install`. -You can make a `.gitignore` file in the root of the project, and by writing file or directory names in it, you can tell git what things you don't want to track. It's customary to add `node_modules` to `.gitignore`, since it can get really big. +You can make a `.gitignore` file in the root of the project, and by writing file or directory names in it, you can tell git what things you don't want to track. It's customary to add `node_modules` to `.gitignore`, since it can get really big. Similarly, `dist` is often ignored as it can be generated when someone runs the command to bundle/build the application. -When creating a new repo on GitHub there is an option to specify a `.gitignore` template. There are many templates out there that include common files and directories that are not typically tracked based on the type of project or language used. When looking for a template for JavaScript projects there is a `node` template that includes `node_modules`. +When creating a new repo on GitHub, there is an option to specify a `.gitignore` template. There are many templates out there that include common files and directories that are not typically tracked based on the type of project or language used. For JavaScript projects, there is a `node` template that includes `node_modules` and `dist`.
@@ -20,49 +20,24 @@ When creating a new repo on GitHub there is an option to specify a `.gitignore`
-1. Start the project the same way you began the webpack tutorial project. - 1. Run `npm init` in your project directory to generate a `package.json` file. +1. Start the project the same way you began the webpack tutorial project, by creating the `package.json` file and setting up Webpack. + - Remember, you only need to install and configure the things you need for your project. For example, if you do not plan to have local image files linked in your HTML template, you will not need to install and configure `html-loader`. +1. Create a `.gitignore` file in the root of your project. It should contain the text `node_modules` and `dist` on separate lines. - 1. Run `npm install webpack webpack-cli --save-dev` to install webpack to the node_modules directory of your project. - - 1. Create a `src` and `dist` directory with the following contents: - 1. An `index.js` file in `src`. - - 1. An `index.html` file in `src`. This file will not need a script tag, because we're using `html-webpack-plugin`, which automatically adds that in. You will also not need to link a CSS stylesheet as you should be importing it into your JavaScript and letting your webpack configuration handle bundling. - - 1. Create a `webpack.config.js` file that looks just like our file from the [Webpack "Getting Started" tutorial](https://webpack.js.org/guides/getting-started/#using-a-configuration). Don't forget to add the `html-webpack-plugin` config to your `webpack.config.js` and set its `template` option with a path to `src/index.html`. - -1. Create a `.gitignore` file in the root of your project. It should contain `node_modules` and `dist` on separate lines. - -1. Set up an HTML skeleton inside of `src/index.html`. Inside the body, add a `
` element that contains a `
### Knowledge check -This section contains questions for you to check your understanding of this lesson. If you're having trouble answering the questions below on your own, review the material above to find the answer. - * How do you register a callback? - * What events happen in an Active Record object's lifecycle? - * How can you make a callback run under specific conditions? - * When are transaction callbacks most useful? +The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. + +- [How do you register a callback?](#using-callbacks) +- [What events happen in an Active Record object's lifecycle?](#the-life-cycle-of-an-active-record-object) +- [How can you make a callback run under specific conditions?](#specifying-callback-characteristics) +- [When are transaction callbacks most useful?](https://guides.rubyonrails.org/active_record_callbacks.html#transaction-callbacks) ### Additional resources diff --git a/ruby_on_rails/advanced_forms_and_activerecord/active_record_queries.md b/ruby_on_rails/advanced_forms_and_activerecord/active_record_queries.md index 41ce36f23b1..a54afea1834 100644 --- a/ruby_on_rails/advanced_forms_and_activerecord/active_record_queries.md +++ b/ruby_on_rails/advanced_forms_and_activerecord/active_record_queries.md @@ -86,10 +86,10 @@ The new concept is how to check whether an object actually exists yet or not, wh There are multiple ways to submit arguments for most Rails query methods. You can typically use either symbols or strings or both. We prefer to stick with symbols and hashes wherever possible. You can also use `?` parameters like in normal SQL. When it's not ambiguous (e.g. if you aren't working with multiple tables) you can also choose to specify the table name or not (see #5 below). All of the following are the same: 1. `User.where(email: "foo@bar.com")` -2. `User.where("email" => "foo@bar.com")` -3. `User.where("email = 'foo@bar.com'")` -4. `User.where("email = ?", "foo@bar.com")` -5. `User.where("users.email" => "foo@bar.com")` +1. `User.where("email" => "foo@bar.com")` +1. `User.where("email = 'foo@bar.com'")` +1. `User.where("email = ?", "foo@bar.com")` +1. `User.where("users.email" => "foo@bar.com")` #### More assorted querying knowledge @@ -212,32 +212,33 @@ How much do you need to understand or care about scopes? In the early going, you Sometimes, you just can't get ActiveRecord to do what you want it to. In that case, it gives you an interface to the bare metal SQL so you can just type in your query as desired. This should really be a last resort -- it's basically hard-coding your application code. Use the `#find_by_sql` method for this. +### Conclusion + +This was a lot of material, but you should have a healthy appreciation for the breadth of things that you can do with Active Record. At the most basic level, though, you can do pretty much anything you can in SQL by using Active Record query methods. You'll get a chance to use some of these newfound query methods in future projects and others will come up when you're building things on your own. + ### Assignment
-### Querying basics +#### Querying basics 1. Read the first 6 sections of the [Rails Guide on Active Record Querying](http://guides.rubyonrails.org/active_record_querying.html) for a more basic overview of query functions. Don't worry too much about batching and `#find_each`. -2. Read section 20 of the [same Rails Guide](https://guides.rubyonrails.org/active_record_querying.html#existence-of-objects) for a brief look at using `exists?`, `any?` and `many?`. -3. Read sections 7, 8 and 21 of the [same Rails Guide](https://guides.rubyonrails.org/active_record_querying.html#group) for an understanding of aggregate functions and the calculations you can run on them. -4. Skim sections 9-12 of the [same Rails Guide](https://guides.rubyonrails.org/active_record_querying.html#overriding-conditions). -5. Read section 12 of the [same Rails Guide](https://guides.rubyonrails.org/active_record_querying.html#joining-tables) to see how Rails lets you play with joining tables together. -6. Read section 18 of the [same Rails Guide](https://guides.rubyonrails.org/active_record_querying.html#find-or-build-a-new-object) for a quick look at the helpful `find_or_create_by` methods. +1. Read section 20 of the same Rails guide for a brief look at [using `exists?`, `any?` and `many?`](https://guides.rubyonrails.org/active_record_querying.html#existence-of-objects). +1. Read sections 7, 8 and 21 of the same Rails guide for an understanding of [aggregate functions and the calculations you can run on them](https://guides.rubyonrails.org/active_record_querying.html#grouping). +1. Skim sections 9-12 of the same Rails guide on [overriding conditions](https://guides.rubyonrails.org/active_record_querying.html#overriding-conditions). +1. Read section 12 of the same Rails guide to see how Rails lets you play with [joining tables together](https://guides.rubyonrails.org/active_record_querying.html#joining-tables). +1. Read section 18 of the same Rails guide for a quick look at [the helpful `find_or_create_by` methods](https://guides.rubyonrails.org/active_record_querying.html#find-or-build-a-new-object). -### Advanced querying +#### Advanced querying 1. Read section 14 in the [Rails Guide on Querying](https://guides.rubyonrails.org/active_record_querying.html#scopes) for a look at scopes. Again, you don't necessarily need to memorize all the details of scopes, but you should understand the concept and when it might be useful. -2. Read section 19 of the [same Rails Guide](http://guides.rubyonrails.org/active_record_querying.html#finding-by-sql) for a look at using SQL directly. -
+1. Read section 19 of the same Rails guide for a look at [using SQL directly to query](http://guides.rubyonrails.org/active_record_querying.html#finding-by-sql). -### Conclusion - -This was a lot of material, but you should have a healthy appreciation for the breadth of things that you can do with Active Record. At the most basic level, though, you can do pretty much anything you can in SQL by using Active Record query methods. You'll get a chance to use some of these newfound query methods in future projects and others will come up when you're building things on your own. +
### Knowledge check -This section contains questions for you to check your understanding of this lesson on your own. If you’re having trouble answering a question, click it and review the material it links to. +The following questions are an opportunity to reflect on key topics in this lesson. If you can't answer a question, click on it to review the material, but keep in mind you are not expected to memorize or master this knowledge. - [How does lazy evaluation help make Active Record more efficient?](#relations-and-lazy-evaluation) - [How do you check whether a database already contains a record?](#checking-for-existence) @@ -249,7 +250,7 @@ This section contains questions for you to check your understanding of this less ### Additional resources -This section contains helpful links to related content. It isn’t required, so consider it supplemental. +This section contains helpful links to related content. It isn't required, so consider it supplemental. - [SO post on Using Scopes vs Class Methods](http://stackoverflow.com/questions/5899765/activerecord-rails-3-scope-vs-class-method) - [Platformatec diving more into the use case of scopes vs class methods](http://blog.plataformatec.com.br/2013/02/active-record-scopes-vs-class-methods/) diff --git a/ruby_on_rails/advanced_forms_and_activerecord/forms_advanced.md b/ruby_on_rails/advanced_forms_and_activerecord/forms_advanced.md index 104bbcedf19..e2081162beb 100644 --- a/ruby_on_rails/advanced_forms_and_activerecord/forms_advanced.md +++ b/ruby_on_rails/advanced_forms_and_activerecord/forms_advanced.md @@ -14,13 +14,13 @@ This section contains a general overview of topics that you will learn in this l - How to whitelist nested parameters. - How to delete records via form fields. -### Prepopulating `select` tags with collections +### Prepopulating select tags with collections Rails provides you with a few handy ways of making dropdown menus which already contain data when the form is loaded (otherwise they're not that useful). Let's say you want to build a New Post form for your blog but you want to be able to select who the author is from among your list of users. You will need to make a dropdown which submits the user's ID as a part of your `params` hash. So you might populate `@users` in your posts controller: -~~~ruby +```ruby # app/controllers/posts_controller.rb ... def new @@ -28,11 +28,11 @@ Let's say you want to build a New Post form for your blog but you want to be abl @post = Post.new end ... -~~~ +``` The bare HTML way is to build a bunch of `