From 19faa09c9b527efee1ebd580a2cbe67b01bbfb64 Mon Sep 17 00:00:00 2001 From: Naomi Carrigan Date: Wed, 26 Jul 2023 11:38:44 -0700 Subject: [PATCH] feat: remove legacy RWD projects (#50960) --- client/i18n/locales/english/intro.json | 14 +- .../Introduction/super-block-intro.tsx | 1 + client/src/utils/superblock-map-titles.ts | 1 + .../responsive-web-design-projects/meta.json | 34 -- .../build-a-personal-portfolio-webpage.md | 281 ---------- .../build-a-product-landing-page.md | 470 ---------------- .../build-a-survey-form.md | 518 ----------------- .../build-a-technical-documentation-page.md | 529 ------------------ .../build-a-tribute-page.md | 325 ----------- .../challenges/multifile-cert-project.ts | 6 +- cypress/e2e/default/learn/index.ts | 2 +- .../default/legacy/redirects/challenges.ts | 2 +- 12 files changed, 11 insertions(+), 2172 deletions(-) delete mode 100644 curriculum/challenges/_meta/responsive-web-design-projects/meta.json delete mode 100644 curriculum/challenges/english/01-responsive-web-design/responsive-web-design-projects/build-a-personal-portfolio-webpage.md delete mode 100644 curriculum/challenges/english/01-responsive-web-design/responsive-web-design-projects/build-a-product-landing-page.md delete mode 100644 curriculum/challenges/english/01-responsive-web-design/responsive-web-design-projects/build-a-survey-form.md delete mode 100644 curriculum/challenges/english/01-responsive-web-design/responsive-web-design-projects/build-a-technical-documentation-page.md delete mode 100644 curriculum/challenges/english/01-responsive-web-design/responsive-web-design-projects/build-a-tribute-page.md diff --git a/client/i18n/locales/english/intro.json b/client/i18n/locales/english/intro.json index 37ab41fba6a..da157bf0cd4 100644 --- a/client/i18n/locales/english/intro.json +++ b/client/i18n/locales/english/intro.json @@ -1,6 +1,6 @@ { "responsive-web-design": { - "title": "Legacy Responsive Web Design", + "title": "Legacy Responsive Web Design Challenges", "intro": [ "In this Responsive Web Design Certification, you'll learn the languages that developers use to build webpages: HTML (Hypertext Markup Language) for content, and CSS (Cascading Style Sheets) for design.", "First, you'll build a cat photo app to learn the basics of HTML and CSS. Later, you'll learn modern techniques like CSS variables by building a penguin, and best practices for accessibility by building a web form.", @@ -56,13 +56,6 @@ "The CSS grid is a newer standard that makes it easy to build complex responsive layouts. It works by turning an HTML element into a grid, and lets you place child elements anywhere within.", "In this course, you'll learn the fundamentals of CSS grid by building different complex layouts, including a blog." ] - }, - "responsive-web-design-projects": { - "title": "Responsive Web Design Projects", - "intro": [ - "Time to put your newly learnt skills to work. By working on these projects, you will get a chance to apply all of the skills, principles, and concepts you have learned so far: HTML, CSS, Visual Design, Accessibility, and more.", - "Complete the five web programming projects below to earn your Responsive Web Design certification." - ] } } }, @@ -458,7 +451,10 @@ "In these projects, you'll need to fetch data and parse a dataset, then use D3 to create different data visualizations. Finish them all to earn your Data Visualization certification." ] }, - "d3-dashboard": { "title": "D3 Dashboard", "intro": ["", ""] } + "d3-dashboard": { + "title": "D3 Dashboard", + "intro": ["", ""] + } } }, "relational-database": { diff --git a/client/src/templates/Introduction/super-block-intro.tsx b/client/src/templates/Introduction/super-block-intro.tsx index 66aead727f7..2f75ddcdcdf 100644 --- a/client/src/templates/Introduction/super-block-intro.tsx +++ b/client/src/templates/Introduction/super-block-intro.tsx @@ -181,6 +181,7 @@ const SuperBlockIntroductionPage = (props: SuperBlockProp) => { const defaultCurriculumNames = blockDashedNames; const superblockWithoutCert = [ + SuperBlocks.RespWebDesign, SuperBlocks.CodingInterviewPrep, SuperBlocks.TheOdinProject, SuperBlocks.ProjectEuler diff --git a/client/src/utils/superblock-map-titles.ts b/client/src/utils/superblock-map-titles.ts index 3876e09ee8e..25e82b4b2f1 100644 --- a/client/src/utils/superblock-map-titles.ts +++ b/client/src/utils/superblock-map-titles.ts @@ -10,6 +10,7 @@ enum SuperBlockI18nKeys { // the map and window. e.g. 'Certification' in Responsive Web Design // Certification const superBlocksWithoutLastWord = [ + SuperBlocks.RespWebDesign, SuperBlocks.CodingInterviewPrep, SuperBlocks.TheOdinProject, SuperBlocks.ProjectEuler diff --git a/curriculum/challenges/_meta/responsive-web-design-projects/meta.json b/curriculum/challenges/_meta/responsive-web-design-projects/meta.json deleted file mode 100644 index b1a6dd5975f..00000000000 --- a/curriculum/challenges/_meta/responsive-web-design-projects/meta.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "Responsive Web Design Projects", - "isUpcomingChange": false, - "usesMultifileEditor": true, - "dashedName": "responsive-web-design-projects", - "helpCategory": "HTML-CSS", - "order": 7, - "time": "150 hours", - "template": "", - "required": [], - "superBlock": "responsive-web-design", - "challengeOrder": [ - { - "id": "bd7158d8c442eddfaeb5bd18", - "title": "Build a Tribute Page" - }, - { - "id": "587d78af367417b2b2512b03", - "title": "Build a Survey Form" - }, - { - "id": "587d78af367417b2b2512b04", - "title": "Build a Product Landing Page" - }, - { - "id": "587d78b0367417b2b2512b05", - "title": "Build a Technical Documentation Page" - }, - { - "id": "bd7158d8c242eddfaeb5bd13", - "title": "Build a Personal Portfolio Webpage" - } - ] -} \ No newline at end of file diff --git a/curriculum/challenges/english/01-responsive-web-design/responsive-web-design-projects/build-a-personal-portfolio-webpage.md b/curriculum/challenges/english/01-responsive-web-design/responsive-web-design-projects/build-a-personal-portfolio-webpage.md deleted file mode 100644 index afe98f114e4..00000000000 --- a/curriculum/challenges/english/01-responsive-web-design/responsive-web-design-projects/build-a-personal-portfolio-webpage.md +++ /dev/null @@ -1,281 +0,0 @@ ---- -id: bd7158d8c242eddfaeb5bd13 -title: Build a Personal Portfolio Webpage -challengeType: 14 -forumTopicId: 301143 -dashedName: build-a-personal-portfolio-webpage ---- - -# --description-- - -**Objective:** Build an app that is functionally similar to https://personal-portfolio.freecodecamp.rocks - -**User Stories:** - -1. Your portfolio should have a welcome section with an `id` of `welcome-section` -1. The welcome section should have an `h1` element that contains text -1. Your portfolio should have a projects section with an `id` of `projects` -1. The projects section should contain at least one element with a `class` of `project-tile` to hold a project -1. The projects section should contain at least one link to a project -1. Your portfolio should have a navbar with an id of `navbar` -1. The navbar should contain at least one link that you can click on to navigate to different sections of the page -1. Your portfolio should have a link with an id of `profile-link`, which opens your GitHub or freeCodeCamp profile in a new tab -1. Your portfolio should have at least one media query -1. The height of the welcome section should be equal to the height of the viewport -1. The navbar should always be at the top of the viewport - -Fulfill the user stories and pass all the tests below to complete this project. Give it your own personal style. Happy Coding! - -**Note:** Be sure to add `` in your HTML to link your stylesheet and apply your CSS - -# --hints-- - -Your portfolio should have a "Welcome" section with an `id` of `welcome-section`. - -```js -const el = document.getElementById('welcome-section') -assert(!!el); -``` - -Your `#welcome-section` element should contain an `h1` element. - -```js -assert.isAbove( - document.querySelectorAll('#welcome-section h1').length, - 0, - 'Welcome section should contain an h1 element ' -); -``` - -You should not have any empty `h1` elements within `#welcome-section` element. - -```js -assert.isAbove( - document.querySelectorAll('#welcome-section h1')?.[0]?.innerText?.length, - 0, - 'h1 element in welcome section should contain your name or camper ' + - 'name ' -); -``` - -You should have a "Projects" section with an `id` of `projects`. - -```js -const el = document.getElementById('projects') -assert(!!el); -``` - -Your portfolio should contain at least one element with a class of `project-tile`. - -```js -assert.isAbove( - document.querySelectorAll('#projects .project-tile').length, - 0 -); -``` - -Your `#projects` element should contain at least one `a` element. - -```js -assert.isAbove(document.querySelectorAll('#projects a').length, 0); -``` - -Your portfolio should have a navbar with an `id` of `navbar`. - -```js -const el = document.getElementById('navbar'); -assert(!!el); -``` - -Your `#navbar` element should contain at least one `a` element whose `href` attribute starts with `#`. - -```js -const links = [...document.querySelectorAll('#navbar a')].filter( - (nav) => (nav?.getAttribute('href') || '').substring(0, 1) === '#' -); - -assert.isAbove( - links.length, - 0, - 'Navbar should contain an anchor link ' -); -``` - -Your portfolio should have an `a` element with an `id` of `profile-link`. - -```js -const el = document.getElementById('profile-link'); -assert(!!el && el.tagName === 'A') -``` - -Your `#profile-link` element should have a `target` attribute of `_blank`. - -```js -const el = document.getElementById('profile-link'); -assert(!!el && el.target === '_blank') -``` - -Your portfolio should use at least one media query. - -```js -const htmlSourceAttr = Array.from(document.querySelectorAll('source')).map(el => el.getAttribute('media')) -const cssCheck = new __helpers.CSSHelp(document).getCSSRules('media') -assert(cssCheck.length > 0 || htmlSourceAttr.length > 0); -``` - -Your `#navbar` element should always be at the top of the viewport. - -```js -(async () => { - const timeout = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)); - - const navbar = document.getElementById('navbar'); - assert.approximately( - navbar?.getBoundingClientRect().top, - 0, - 15, - "Navbar's parent should be body and it should be at the top of " + - 'the viewport ' - ); - - window.scroll(0, 500); - - await timeout(1); - - assert.approximately( - navbar?.getBoundingClientRect().top, - 0, - 15, - 'Navbar should be at the top of the viewport even after ' + - 'scrolling ' - ); - window.scroll(0, 0); -})(); -``` - -# --seed-- - -## --seed-contents-- - -```html - -``` - -```css - -``` - -## --solutions-- - -```html - - - - - - Personal Portfolio - - - - - -
-
-
-

It's me!

- -

Naomi Carrigan

-

Welcome to my portfolio page!

-

-
-

Projects

-

Here's what I've worked on!

-

- - - - -


-
-

Contact me!

-

Use the links below to get in touch.

-

FreeCodeCamp.org | GitHub | Facebook | LinkedIn -

- - - -``` - -```css -nav{ - position: fixed; - width: 100%; - text-align: right; - font-size: 24pt; - top: 0%; - right: 5px; - background-color: #000000; - color: #ffffff; -} -@media (max-width: 500px){ - nav{ - display: none; - } -} -a{ - color: #ffffff; -} -main{ - text-align: center; - background-color: black; - font-family:Pacifico -} -h1{ - font-size: 48pt; -} -h2{ - font-size: 24pt; -} -p{ - font-size: 12pt; -} -#welcome-section{ - background-color:#251a4a; - color: #FFFFFF; - display: table-cell; - vertical-align: middle; - width: 100vw; - height: 100vh; -} -#projects{ - background-color: #060a9c; - color: #ffffff; - display: table-cell; - vertical-align: middle; - width: 100vw; - height: 100vh; -} -#contact{ - background-color: #03300b; - color: #ffffff; - display: table-cell; - vertical-align: middle; - width: 100vw; - height: 100vh; -} -``` diff --git a/curriculum/challenges/english/01-responsive-web-design/responsive-web-design-projects/build-a-product-landing-page.md b/curriculum/challenges/english/01-responsive-web-design/responsive-web-design-projects/build-a-product-landing-page.md deleted file mode 100644 index 70afaee2f1a..00000000000 --- a/curriculum/challenges/english/01-responsive-web-design/responsive-web-design-projects/build-a-product-landing-page.md +++ /dev/null @@ -1,470 +0,0 @@ ---- -id: 587d78af367417b2b2512b04 -title: Build a Product Landing Page -challengeType: 14 -forumTopicId: 301144 -dashedName: build-a-product-landing-page ---- - -# --description-- - -**Objective:** Build an app that is functionally similar to https://product-landing-page.freecodecamp.rocks - -**User Stories:** - -1. Your product landing page should have a `header` element with a corresponding `id="header"` -1. You can see an image within the `header` element with a corresponding `id="header-img"` (A logo would make a good image here) -1. Within the `#header` element, you can see a `nav` element with a corresponding `id="nav-bar"` -1. You can see at least three clickable elements inside the `nav` element, each with the class `nav-link` -1. When you click a `.nav-link` button in the `nav` element, you are taken to the corresponding section of the landing page -1. You can watch an embedded product video with `id="video"` -1. Your landing page has a `form` element with a corresponding `id="form"` -1. Within the form, there is an `input` field with `id="email"` where you can enter an email address -1. The `#email` input field should have placeholder text to let users know what the field is for -1. The `#email` input field uses HTML5 validation to confirm that the entered text is an email address -1. Within the form, there is a submit `input` with a corresponding `id="submit"` -1. When you click the `#submit` element, the email is submitted to a static page (use this mock URL: `https://www.freecodecamp.com/email-submit`) -1. The navbar should always be at the top of the viewport -1. Your product landing page should have at least one media query -1. Your product landing page should utilize CSS flexbox at least once - -Fulfill the user stories and pass all the tests below to complete this project. Give it your own personal style. Happy Coding! - -**Note:** Be sure to add `` in your HTML to link your stylesheet and apply your CSS - -# --hints-- - -You should have a `header` element with an `id` of `header`. - -```js -const el = document.getElementById('header') -assert(!!el && el.tagName === 'HEADER') -``` - -You should have an `img` element with an `id` of `header-img`. - -```js -const el = document.getElementById('header-img') -assert(!!el && el.tagName === 'IMG') -``` - -Your `#header-img` should be a descendant of the `#header`. - -```js -const els = document.querySelectorAll('#header #header-img') -assert(els.length > 0) -``` - -Your `#header-img` should have a `src` attribute. - -```js -const el = document.getElementById('header-img') -assert(!!el && !!el.src) -``` - -Your `#header-img`’s `src` value should be a valid URL (starts with `http`). - -```js -const el = document.getElementById('header-img') -assert(!!el && /^http/.test(el.src)) -``` - -You should have a `nav` element with an `id` of `nav-bar`. - -```js -const el = document.getElementById('nav-bar') -assert(!!el && el.tagName === 'NAV') -``` - -Your `#nav-bar` should be a descendant of the `#header`. - -```js -const els = document.querySelectorAll('#header #nav-bar') -assert(els.length > 0) -``` - -You should have at least 3 `.nav-link` elements within the `#nav-bar`. - -```js -const els = document.querySelectorAll('#nav-bar .nav-link') -assert(els.length >= 3) -``` - -Each `.nav-link` element should have an `href` attribute. - -```js -const els = document.querySelectorAll('.nav-link') -els.forEach(el => { - if (!el.href) assert(false) -}) -assert(els.length > 0) -``` - -Each `.nav-link` element should link to a corresponding element on the landing page (has an `href` with a value of another element's id. e.g. `#footer`). - -```js -const els = document.querySelectorAll('.nav-link') -els.forEach(el => { - const linkDestination = el.getAttribute('href').slice(1) - if (!document.getElementById(linkDestination)) assert(false) -}) -assert(els.length > 0) -``` - -You should have a `video` or `iframe` element with an `id` of `video`. - -```js -const el = document.getElementById('video') -assert(!!el && (el.tagName === 'VIDEO' || el.tagName === 'IFRAME')) -``` - -Your `#video` should have a `src` attribute. - -```js -let el = document.getElementById('video') -const sourceNode = el.children; -let sourceElement = null; -if (sourceNode.length) { - sourceElement = [...video.children].filter(el => el.localName === 'source')[0]; -} -if (sourceElement) { - el = sourceElement; -} -assert(el.hasAttribute('src')); -``` - -You should have a `form` element with an `id` of `form`. - -```js -const el = document.getElementById('form') -assert(!!el && el.tagName === 'FORM') -``` - -You should have an `input` element with an `id` of `email`. - -```js -const el = document.getElementById('email') -assert(!!el && el.tagName === 'INPUT') -``` - -Your `#email` should be a descendant of the `#form`. - -```js -const els = document.querySelectorAll('#form #email') -assert(els.length > 0) -``` - -Your `#email` should have the `placeholder` attribute with placeholder text. - -```js -const el = document.getElementById('email') -assert(!!el && !!el.placeholder && el.placeholder.length > 0) -``` - -Your `#email` should use HTML5 validation by setting its `type` to `email`. - -```js -const el = document.getElementById('email') -assert(!!el && el.type === 'email') -``` - -You should have an `input` element with an `id` of `submit`. - -```js -const el = document.getElementById('submit') -assert(!!el && el.tagName === 'INPUT') -``` - -Your `#submit` should be a descendant of the `#form`. - -```js -const els = document.querySelectorAll('#form #submit') -assert(els.length > 0) -``` - -Your `#submit` should have a `type` of `submit`. - -```js -const el = document.getElementById('submit') -assert(!!el && el.type === 'submit') -``` - -Your `#form` should have an `action` attribute of `https://www.freecodecamp.com/email-submit`. - -```js -const el = document.getElementById('form') -assert(!!el && el.action === 'https://www.freecodecamp.com/email-submit') -``` - -Your `#email` should have a `name` attribute of `email`. - -```js -const el = document.getElementById('email') -assert(!!el && el.name === 'email') -``` - -Your `#nav-bar` should always be at the top of the viewport. - -```js -(async () => { - const timeout = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)); - - const header = document.getElementById('header'); - const headerChildren = header.children; - const navbarCandidates = [header, ...headerChildren]; - - // Return smallest top position of all navbar candidates - const getNavbarPosition = (candidates = []) => { - return candidates.reduce( - (min, candidate) => - Math.min(min, Math.abs(candidate?.getBoundingClientRect().top)), - Infinity - ); - }; - assert.approximately( - getNavbarPosition(navbarCandidates), - 0, - 15, - '#header or one of its children should be at the top of the viewport ' - ); - - window.scroll(0, 500); - await timeout(1); - - assert.approximately( - getNavbarPosition(navbarCandidates), - 0, - 15, - '#header or one of its children should be at the top of the ' + - 'viewport even after scrolling ' - ); - - window.scroll(0, 0); -})(); -``` - -Your Product Landing Page should use at least one media query. - -```js -const htmlSourceAttr = Array.from(document.querySelectorAll('source')).map(el => el.getAttribute('media')) -const cssCheck = new __helpers.CSSHelp(document).getCSSRules('media') -assert(cssCheck.length > 0 || htmlSourceAttr.length > 0); -``` - -Your Product Landing Page should use CSS Flexbox at least once. - -```js -const hasFlex = (rule) => ["flex", "inline-flex"].includes(rule.style?.display) -const stylesheet = new __helpers.CSSHelp(document).getStyleSheet() -const cssRules = new __helpers.CSSHelp(document).styleSheetToCssRulesArray(stylesheet) -const mediaRules = new __helpers.CSSHelp(document).getCSSRules('media') -const usesFlex = cssRules.find(rule => hasFlex(rule)) -const usesFlexMedia = mediaRules.find(mediaRule => { - return [...mediaRule.cssRules].find(rule => hasFlex(rule)) -}) -assert(usesFlex || usesFlexMedia) -``` - -# --seed-- - -## --seed-contents-- - -```html - -``` - -```css - -``` - -## --solutions-- - -```html - - - - - - Product Landing Page - - - -
-

- Pokemon Daycare Service -

-
-

What we offer

-
-
- -
-
Guaranteed friendly and loving staff!
-
-
-
- -
-
- Comfortable environment for Pokemon to explore and play! -
-
-
-
- -
-
- Multiple membership plans to fit your lifestyle! -
-
-
-
-

Check us out!

- A sneak peek into our facility: -
- -
-
-

Membership Plans

-
-
- Basic Membership
-
    -
  • One Pokemon
  • -
  • Food and berries provided
  • -
- $9.99/month -
-
- Silver Membership
-
    -
  • Up to Three Pokemon
  • -
  • Food and berries provided
  • -
  • Grooming and accessories included
  • -
- $19.99/month -
-
- Gold Membership
-
    -
  • Up to six Pokemon!
  • -
  • Food and berries provided
  • -
  • Grooming and accessories included
  • -
  • Personal training for each Pokemon
  • -
  • Breeding and egg hatching
  • -
- $29.99/month -
-
-
-
-

Sign up for our newsletter!

- - -
- -
- - -``` - -```css -body { - background-color: #3a3240; - color: white; -} -main { - max-width: 750px; - margin: 50px auto; -} -input { - background-color: #92869c; -} -a:not(.nav-link) { - color: white; -} -#header-img { - max-height: 25px; -} -#nav-bar { - position: fixed; - width: 100%; - text-align: center; - top: 0%; - background-color: #92869c; -} -h1 { - text-align: center; -} -body { - text-align: center; -} -footer { - text-align: center; -} -#bullet { - max-height: 25px; -} -.flex-here { - display: flex; - justify-content: center; -} -.flex-left { - height: 25px; -} -.flex-mem { - display: flex; - justify-content: center; -} -.flex-mem-box { - background-color: #92869c; - border-color: black; - border-width: 5px; - border-style: solid; - margin: 10px; - padding: 10px; - color: black; -} -@media (max-width: 350px) { - #video { - width: 300; - height: 200; - } -} -``` diff --git a/curriculum/challenges/english/01-responsive-web-design/responsive-web-design-projects/build-a-survey-form.md b/curriculum/challenges/english/01-responsive-web-design/responsive-web-design-projects/build-a-survey-form.md deleted file mode 100644 index 0a495af62a6..00000000000 --- a/curriculum/challenges/english/01-responsive-web-design/responsive-web-design-projects/build-a-survey-form.md +++ /dev/null @@ -1,518 +0,0 @@ ---- -id: 587d78af367417b2b2512b03 -title: Build a Survey Form -challengeType: 14 -forumTopicId: 301145 -dashedName: build-a-survey-form ---- - -# --description-- - -**Objective:** Build an app that is functionally similar to https://survey-form.freecodecamp.rocks - -**User Stories:** - -1. You should have a page title in an `h1` element with an `id` of `title` -1. You should have a short explanation in a `p` element with an `id` of `description` -1. You should have a `form` element with an `id` of `survey-form` -1. Inside the form element, you are **required** to enter your name in an `input` field that has an `id` of `name` and a `type` of `text` -1. Inside the form element, you are **required** to enter your email in an `input` field that has an `id` of `email` -1. If you enter an email that is not formatted correctly, you will see an HTML5 validation error -1. Inside the form, you can enter a number in an `input` field that has an `id` of `number` -1. The number input should not accept non-numbers, either by preventing you from typing them or by showing an HTML5 validation error (depending on your browser). -1. If you enter numbers outside the range of the number input, which are defined by the `min` and `max` attributes, you will see an HTML5 validation error -1. For the name, email, and number input fields, you can see corresponding `label` elements in the form, that describe the purpose of each field with the following ids: `id="name-label"`, `id="email-label"`, and `id="number-label"` -1. For the name, email, and number input fields, you can see placeholder text that gives a description or instructions for each field -1. Inside the form element, you should have a `select` dropdown element with an `id` of `dropdown` and at least two options to choose from -1. Inside the form element, you can select an option from a group of at least two radio buttons that are grouped using the `name` attribute -1. Inside the form element, you can select several fields from a series of checkboxes, each of which must have a `value` attribute -1. Inside the form element, you are presented with a `textarea` for additional comments -1. Inside the form element, you are presented with a button with `id` of `submit` to submit all the inputs - -Fulfill the user stories and pass all the tests below to complete this project. Give it your own personal style. Happy Coding! - -**Note:** Be sure to add `` in your HTML to link your stylesheet and apply your CSS - -# --hints-- - -You should have an `h1` element with an `id` of `title`. - -```js -const el = document.getElementById('title') -assert(!!el && el.tagName === 'H1') -``` - -Your `#title` should not be empty. - -```js -const el = document.getElementById('title') -assert(!!el && el.innerText.length > 0) -``` - -You should have a `p` element with an `id` of `description`. - -```js -const el = document.getElementById('description') -assert(!!el && el.tagName === 'P') -``` - -Your `#description` should not be empty. - -```js -const el = document.getElementById('description') -assert(!!el && el.innerText.length > 0) -``` - -You should have a `form` element with an `id` of `survey-form`. - -```js -const el = document.getElementById('survey-form') -assert(!!el && el.tagName === 'FORM') -``` - -You should have an `input` element with an `id` of `name`. - -```js -const el = document.getElementById('name') -assert(!!el && el.tagName === 'INPUT') -``` - -Your `#name` should have a `type` of `text`. - -```js -const el = document.getElementById('name') -assert(!!el && el.type === 'text') -``` - -Your `#name` should require input. - -```js -const el = document.getElementById('name') -assert(!!el && el.required) -``` - -Your `#name` should be a descendant of `#survey-form`. - -```js -const el = document.querySelector('#survey-form #name') -assert(!!el) -``` - -You should have an `input` element with an `id` of `email`. - -```js -const el = document.getElementById('email') -assert(!!el && el.tagName === 'INPUT') -``` - -Your `#email` should have a `type` of `email`. - -```js -const el = document.getElementById('email') -assert(!!el && el.type === 'email') -``` - -Your `#email` should require input. - -```js -const el = document.getElementById('email') -assert(!!el && el.required) -``` - -Your `#email` should be a descendant of `#survey-form`. - -```js -const el = document.querySelector('#survey-form #email') -assert(!!el) -``` - -You should have an `input` element with an `id` of `number`. - -```js -const el = document.getElementById('number') -assert(!!el && el.tagName === 'INPUT') -``` - -Your `#number` should be a descendant of `#survey-form`. - -```js -const el = document.querySelector('#survey-form #number') -assert(!!el) -``` - -Your `#number` should have a `type` of `number`. - -```js -const el = document.getElementById('number') -assert(!!el && el.type === 'number') -``` - -Your `#number` should have a `min` attribute with a numeric value. - -```js -const el = document.getElementById('number') -assert(!!el && el.min && isFinite(el.min)) -``` - -Your `#number` should have a `max` attribute with a numeric value. - -```js -const el = document.getElementById('number') -assert(!!el && el.max && isFinite(el.max)) -``` - -You should have a `label` element with an `id` of `name-label`. - -```js -const el = document.getElementById('name-label') -assert(!!el && el.tagName === 'LABEL') -``` - -You should have a `label` element with an `id` of `email-label`. - -```js -const el = document.getElementById('email-label') -assert(!!el && el.tagName === 'LABEL') -``` - -You should have a `label` element with an `id` of `number-label`. - -```js -const el = document.getElementById('number-label') -assert(!!el && el.tagName === 'LABEL') -``` - -Your `#name-label` should contain text that describes the input. - -```js -const el = document.getElementById('name-label') -assert(!!el && el.innerText.length > 0) -``` - -Your `#email-label` should contain text that describes the input. - -```js -const el = document.getElementById('email-label') -assert(!!el && el.innerText.length > 0) -``` - -Your `#number-label` should contain text that describes the input. - -```js -const el = document.getElementById('number-label') -assert(!!el && el.innerText.length > 0) -``` - -Your `#name-label` should be a descendant of `#survey-form`. - -```js -const el = document.querySelector('#survey-form #name-label') -assert(!!el) -``` - -Your `#email-label` should be a descendant of `#survey-form`. - -```js -const el = document.querySelector('#survey-form #email-label') -assert(!!el) -``` - -Your `#number-label` should be a descendant of `#survey-form`. - -```js -const el = document.querySelector('#survey-form #number-label') -assert(!!el) -``` - -Your `#name` should have a `placeholder` attribute and value. - -```js -const el = document.getElementById('name') -assert(!!el && !!el.placeholder && el.placeholder.length > 0) -``` - -Your `#email` should have a `placeholder` attribute and value. - -```js -const el = document.getElementById('email') -assert(!!el && !!el.placeholder && el.placeholder.length > 0) -``` - -Your `#number` should have a `placeholder` attribute and value. - -```js -const el = document.getElementById('number') -assert(!!el && !!el.placeholder && el.placeholder.length > 0) -``` - -You should have a `select` field with an `id` of `dropdown`. - -```js -const el = document.getElementById('dropdown') -assert(!!el && el.tagName === 'SELECT') -``` - -Your `#dropdown` should have at least two selectable (not disabled) `option` elements. - -```js -const els = document.querySelectorAll('#dropdown option:not([disabled])') -assert(els.length >= 2) -``` - -Your `#dropdown` should be a descendant of `#survey-form`. - -```js -const el = document.querySelector('#survey-form #dropdown') -assert(!!el) -``` - -You should have at least two `input` elements with a `type` of `radio` (radio buttons). - -```js -const els = document.querySelectorAll('input[type="radio"]') -assert(els.length >= 2) -``` - -You should have at least two radio buttons that are descendants of `#survey-form`. - -```js -const els = document.querySelectorAll('#survey-form input[type="radio"]') -assert(els.length >= 2) -``` - -All your radio buttons should have a `value` attribute and value. - -```js -const els1 = document.querySelectorAll('input[type="radio"]') -const els2 = document.querySelectorAll('input[type="radio"][value=""], input[type="radio"]:not([value])') -assert(els1.length > 0 && els2.length === 0) -``` - -All your radio buttons should have a `name` attribute and value. - -```js -const els1 = document.querySelectorAll('input[type="radio"]') -const els2 = document.querySelectorAll('input[type="radio"][name=""], input[type="radio"]:not([name])') -assert(els1.length > 0 && els2.length === 0) -``` - -Every radio button group should have at least 2 radio buttons. - -```js -const radioButtons = document.querySelectorAll('input[type="radio"]'); -const groups = {} - -if (radioButtons) { - radioButtons.forEach(el => { - if (!groups[el.name]) groups[el.name] = [] - groups[el.name].push(el) - }) -} - -const groupKeys = Object.keys(groups) - -groupKeys.forEach(key => { - if (groups[key].length < 2) assert(false) -}) - -assert(groupKeys.length > 0) -``` - -You should have at least two `input` elements with a `type` of `checkbox` (checkboxes) that are descendants of `#survey-form`. - -```js -const els = document.querySelectorAll('#survey-form input[type="checkbox"]'); -assert(els.length >= 2) -``` - -All your checkboxes inside `#survey-form` should have a `value` attribute and value. - -```js -const els1 = document.querySelectorAll('#survey-form input[type="checkbox"]') -const els2 = document.querySelectorAll('#survey-form input[type="checkbox"][value=""], #survey-form input[type="checkbox"]:not([value])') -assert(els1.length > 0 && els2.length === 0) -``` - -You should have at least one `textarea` element that is a descendant of `#survey-form`. - -```js -const el = document.querySelector('#survey-form textarea') -assert(!!el) -``` - -You should have an `input` or `button` element with an `id` of `submit`. - -```js -const el = document.getElementById('submit') -assert(!!el && (el.tagName === 'INPUT' || el.tagName === 'BUTTON')) -``` - -Your `#submit` should have a `type` of `submit`. - -```js -const el = document.getElementById('submit') -assert(!!el && el.type === 'submit') -``` - -Your `#submit` should be a descendant of `#survey-form`. - -```js -const el = document.querySelector('#survey-form #submit') -assert(!!el) -``` - -# --seed-- - -## --seed-contents-- - -```html - -``` - -```css - -``` - -## --solutions-- - -```html - - - - - - Survey Form - - -

Survey Form

-

The card below was built as a sample survey form for freeCodeCamp.

-
-

Join the Togepi Fan Club!

-

- Enter your information here to receive updates about club activities, - our monthly newsletter, and other email communications. -

-
- - - - -

Who is your favourite Pokemon?

- - - -

Which communications do you want to receive?

- - - -

Any other information you would like to share?

- -

- Please note: This form is a proof of concept. Submitting the form - will not actually transmit your data. -

- -
-
- - - -``` - -```css -main { - text-align: center; - background-color: #92869c; - background-blend-mode: lighten; - max-width: 500px; - margin: 20px auto; - border-radius: 50px; - box-shadow: 10px 10px rgba(0, 0, 0, 0.5); - color: black; -} -body { - text-align: center; - background: #3a3240; - color: white; -} -input, textarea, select, button { - background: #3a3240; - color: white; -} -a { - color: white; -} -``` diff --git a/curriculum/challenges/english/01-responsive-web-design/responsive-web-design-projects/build-a-technical-documentation-page.md b/curriculum/challenges/english/01-responsive-web-design/responsive-web-design-projects/build-a-technical-documentation-page.md deleted file mode 100644 index 9b184a652c2..00000000000 --- a/curriculum/challenges/english/01-responsive-web-design/responsive-web-design-projects/build-a-technical-documentation-page.md +++ /dev/null @@ -1,529 +0,0 @@ ---- -id: 587d78b0367417b2b2512b05 -title: Build a Technical Documentation Page -challengeType: 14 -forumTopicId: 301146 -dashedName: build-a-technical-documentation-page ---- - -# --description-- - -**Objective:** Build an app that is functionally similar to https://technical-documentation-page.freecodecamp.rocks - -**User Stories:** - -1. You can see a `main` element with a corresponding `id="main-doc"`, which contains the page's main content (technical documentation) -1. Within the `#main-doc` element, you can see several `section` elements, each with a class of `main-section`. There should be a minimum of five -1. The first element within each `.main-section` should be a `header` element, which contains text that describes the topic of that section. -1. Each `section` element with the class of `main-section` should also have an `id` that corresponds with the text of each `header` contained within it. Any spaces should be replaced with underscores (e.g. The section that contains the header "JavaScript and Java" should have a corresponding `id="JavaScript_and_Java"`) -1. The `.main-section` elements should contain at least ten `p` elements total (not each) -1. The `.main-section` elements should contain at least five `code` elements total (not each) -1. The `.main-section` elements should contain at least five `li` items total (not each) -1. You can see a `nav` element with a corresponding `id="navbar"` -1. The navbar element should contain one `header` element which contains text that describes the topic of the technical documentation -1. Additionally, the navbar should contain link (`a`) elements with the class of `nav-link`. There should be one for every element with the class `main-section` -1. The `header` element in the `#navbar` must come before any link (`a`) elements in the navbar -1. Each element with the class of `nav-link` should contain text that corresponds to the `header` text within each `section` (e.g. if you have a "Hello world" section/header, your navbar should have an element which contains the text "Hello world") -1. When you click on a navbar element, the page should navigate to the corresponding section of the `#main-doc` element (e.g. If you click on a `.nav-link` element that contains the text "Hello world", the page navigates to a `section` element with that id, and contains the corresponding header) -1. On regular sized devices (laptops, desktops), the element with `id="navbar"` should be shown on the left side of the screen and should always be visible to the user -1. Your technical documentation should use at least one media query - -Fulfill the user stories and pass all the tests below to complete this project. Give it your own personal style. Happy Coding! - -**Note:** Be sure to add `` in your HTML to link your stylesheet and apply your CSS - -# --hints-- - -You should have a `main` element with an `id` of `main-doc`. - -```js -const el = document.getElementById('main-doc') -assert(!!el) -``` - -You should have at least five `section` elements with a class of `main-section`. - -```js -const els = document.querySelectorAll('#main-doc section') -assert(els.length >= 5) -``` - -All of your `.main-section` elements should be `section` elements. - -```js -const els = document.querySelectorAll('.main-section') -els.forEach(el => { - if (el.tagName !== 'SECTION') assert(false) -}) -assert(els.length > 0) -``` - -You should have at least five `.main-section` elements that are descendants of `#main-doc`. - -```js -const els = document.querySelectorAll('#main-doc .main-section') -assert(els.length >= 5) -``` - -The first child of each `.main-section` should be a `header` element. - -```js -const els = document.querySelectorAll('.main-section') -els.forEach(el => { - if(el.firstElementChild?.tagName !== 'HEADER') assert(false) -}) -assert(els.length > 0) -``` - -None of your `header` elements should be empty. - -```js -const els = document.querySelectorAll('header') -els.forEach(el => { - if (el.innerText?.length <= 0) assert(false) -}) -assert(els.length > 0) -``` - -All of your `.main-section` elements should have an `id`. - -```js -const els = document.querySelectorAll('.main-section') -els.forEach(el => { - if (!el.id || el.id === '') assert(false) -}) -assert(els.length > 0) -``` - -Each `.main-section` should have an `id` that matches the text of its first child, having any spaces in the child's text replaced with underscores (`_`) for the id's. - -```js -const els = document.querySelectorAll('.main-section') -els.forEach(el => { - const text = el.firstElementChild?.innerText?.replaceAll(' ', '_') - if (el.id?.toUpperCase() !== text?.toUpperCase()) assert(false) -}) -assert(els.length > 0) -``` - -You should have at least 10 `p` elements (total) within your `.main-section` elements. - -```js -const els = document.querySelectorAll('.main-section p') -assert(els.length >= 10) -``` - -You should have at least five `code` elements that are descendants of `.main-section` elements. - -```js -const els = document.querySelectorAll('.main-section code') -assert(els.length >= 5) -``` - -You should have at least five `li` elements that are descendants of `.main-section` elements. - -```js -const els = document.querySelectorAll('.main-section li') -assert(els.length >= 5) -``` - -You should have a `nav` element with an `id` of `navbar`. - -```js -const el = document.getElementById('navbar') -assert(!!el && el.tagName === 'NAV') -``` - -Your `#navbar` should have exactly one `header` element within it. - -```js -const els = document.querySelectorAll('#navbar header') -assert(els.length === 1) -``` - -You should have at least one `a` element with a class of `nav-link`. - -```js -const els = document.querySelectorAll('a.nav-link') -assert(els.length >= 1) -``` - -All of your `.nav-link` elements should be anchor (`a`) elements. - -```js -const els = document.querySelectorAll('.nav-link') -els.forEach(el => { - if (el.tagName !== 'A') assert(false) -}) -assert(els.length > 0) -``` - -All of your `.nav-link` elements should be in the `#navbar`. - -```js -const els1 = document.querySelectorAll('.nav-link') -const els2 = document.querySelectorAll('#navbar .nav-link') -assert(els2.length > 0 && els1.length === els2.length) -``` - -You should have the same number of `.nav-link` and `.main-section` elements. - -```js -const els1 = document.querySelectorAll('.main-section') -const els2 = document.querySelectorAll('.nav-link') -assert(els1.length > 0 && els2.length > 0 && els1.length === els2.length) -``` - -The `header` element in the `#navbar` should come before any link (`a`) elements also in the `#navbar`. - -```js -const navLinks = document.querySelectorAll('#navbar a.nav-link'); -const header = document.querySelector('#navbar header'); -navLinks.forEach((navLink) => { - if ( - ( - header.compareDocumentPosition(navLink) & - Node.DOCUMENT_POSITION_PRECEDING - ) - ) assert(false) -}); -assert(!!header) -``` - -Each `.nav-link` should have text that corresponds to the `header` text of its related `section` (e.g. if you have a "Hello world" section/header, your `#navbar` should have a `.nav-link` which has the text "Hello world"). - -```js -const headerText = Array.from(document.querySelectorAll('.main-section')).map(el => - el.firstElementChild?.innerText?.trim().toUpperCase() -) -const linkText = Array.from(document.querySelectorAll('.nav-link')).map(el => - el.innerText?.trim().toUpperCase() -) -const remainder = headerText.filter(str => linkText.indexOf(str) === -1) -assert(headerText.length > 0 && headerText.length > 0 && remainder.length === 0) -``` - -Each `.nav-link` should have an `href` attribute that links to its corresponding `.main-section` (e.g. If you click on a `.nav-link` element that contains the text "Hello world", the page navigates to a `section` element with that id). - -```js -const hrefValues = Array.from(document.querySelectorAll('.nav-link')).map(el => el.getAttribute('href')) -const mainSectionIDs = Array.from(document.querySelectorAll('.main-section')).map(el => el.id) -const missingHrefValues = mainSectionIDs.filter(str => hrefValues.indexOf('#' + str) === -1) -assert(hrefValues.length > 0 && mainSectionIDs.length > 0 && missingHrefValues.length === 0) -``` - -Your `#navbar` should always be on the left edge of the window. - -```js -const el = document.getElementById('navbar') -const left1 = el?.offsetLeft -const left2 = el?.offsetLeft -assert(!!el && left1 >= -15 && left1 <= 15 && left2 >= -15 && left2 <= 15) -``` - -Your Technical Documentation project should use at least one media query. - -```js -const htmlSourceAttr = Array.from(document.querySelectorAll('source')).map(el => el.getAttribute('media')) -const cssCheck = new __helpers.CSSHelp(document).getCSSRules('media') -assert(cssCheck.length > 0 || htmlSourceAttr.length > 0); -``` - -# --seed-- - -## --seed-contents-- - -```html - -``` - -```css - -``` - -## --solutions-- - -```html - - - - - - Technical Documentation Page - - - -
-
-
Introduction
-

- Welcome to a basic introduction of algebra. In this tutorial, we will - review some of the more common algebraic concepts. -

-
-
-
Definitions
-

- To start with, let's define some of the more common terms used in - algebra: -

-
    -
  • - Variable: A variable is an unknown value, usually represented - by a letter. -
  • -
  • - Expression: Essentially a mathematical object. For the - purpose of this tutorial, an expression is one part of an equation. -
  • -
  • - Equation: An equation is a mathematical argument in which two - expressions result in the same value. -
  • -
-
-
-
Examples
-

- Sometimes it is easier to understand the definitions when you have a - physical example to look at. Here is an example of the above terms.

- x + 5 = 12

- In this above example, we have: -

-
    -
  • Variable: The variable in the example is "x".
  • -
  • - Expression: There are two expressions in this example. They - are "x+5" and "12". -
  • -
  • - Equation: The entire example, "x+5=12", is an equation. -
  • -
-
-
-
Solving Equations
-

- The primary use for algebra is to determine an unknown value, the - "variable", with the information provided. Continuing to use our - example from above, we can find the value of the variable "x".

- x + 5 = 12

- In an equation, both sides result in the same value. So you can - manipulate the two expressions however you need, as long as you - perform the same operation (or change) to each side. You do this - because the goal when solving an equation is to - get the variable into its own expression, or by itself on one side - of the = sign.
For this example, we want to remove the "+5" so the "x" is - alone. To do this, we can subtract 5, because subtraction is - the opposite operation to addition. But remember, we have to perform - the same operation to both sides of the equation. Now our equation - looks like this.

- x + 5 - 5 = 12 - 5

- The equation looks like a mess right now, because we haven't completed - the operations. We can simplify this equation to make it easier - to read by performing the operations "5-5" and "12-5". The result - is:

- x = 7

- We now have our solution to this equation! -

-
-
-
Solving Equations II
-

- Let us look at a slightly more challenging equation.

- 3x + 4 = 13

- Again we can start with subtraction. In this case, we want to subtract - 4 from each side of the equation. We will also go ahead and simplify - with each step. So now we have:

- 3x = 9

- "3x" translates to "3*x", where the "*" symbol indicates - multiplication. We use the "*" to avoid confusion, as the "x" is now a - variable instead of a multiplication symbol. The opposite operation - for multiplication is division, so we need to - divide each expression by 3.

- x = 3

- And now we have our solution! -

-
-
-
Solving Equations III
-

- Now we are getting in to more complex operations. Here is another - equation for us to look at:

- x^2 - 8 = 8

- Our very first step will be to add 8 to each side. This is - different from our previous examples, where we had to subtract. But - remember, our goal is to get the variable alone by performing opposite - operations.

- x^2 = 16

- But what does the "^2" mean? The "^" symbol is used to denote - exponents in situations where superscript is not available. When - superscript is available, you would see it as x2. - For the sake of this project, however, we will use the "^" symbol.
- An exponent tells you how many times the base (in our case, "x") is - multiplied by itself. So, "x^2" would be the same as "x*x". Now the - opposite function of multiplication is division, but we would have to - divide both sides by "x". We do not want to do this, as that - would put an "x" on the other side of the equation. So instead, we - need to use the root operation! For an exponent of "2", we call this - the "square root" and denote it with "√". Our equation is now: -

- x = √9

- Performing a root operation by hand can be a tedious process, so we - recommend using a calculator when necessary. However, we are lucky in - that "9" is a - perfect square, so we do not need to calculate anything. Instead, we find our - answer to be:

- x = 3 -

-
-
-
System of Equations
-

- As you explore your algebra studies further, you may start to run - across equations with more than one variable. The first such equations - will likely look like:

- y = 3x

- An equation like this does not have one single solution. - Rather, there are a series of values for which the equation is true. - For example, if "x=3" and "y=9", the equation is true. These equations - are usually used to plot a graph.
- Getting more complicated, though, you may be given a pair of - equations. This is called a "system of equations", and CAN be solved. - Let's look at how we do this! Consider the following system of - equations:

- y = 3x | y - 6 = x - A system of equations IS solvable, but it is a multi-step process. To - get started, we need to chose a variable we are solving for. Let's - solve for "x" first. From the second equation, we know that "x" equals - "y - 6", but we cannot simplify that further because we do not have a - value for "y". Except, thanks to the system of equations, we DO have a - value for "y". We know that "y" equals "3x". So, looking at our second - equation, we can replace "y" with "3x" because they have the same - value. We then get:

- 3x - 6 = x

- Now we can solve for "x"! We start by adding 6 to each side.

- 3x = x + 6

- We still need to get "x" by itself, so we subtract "x" from both sides - and get:

- 2x = 6

- If this confuses you, remember that "3x" is the same as "x+x+x". - Subtract an "x" from that and you get "x+x", or "2x". Now we divide - both sides by 2 and have our value for x!

- x = 3

- However, our work is not done yet. We still need to find the value for - "y". Let's go back to our first equation:

- y = 3x

- We have a value for "x" now, so let's see what happens if we put that - value in.

- y = 3*3

- We perform the multiplication and discover that "y=9"! Our solution to - this system of equations then is:

- x = 3 and y = 9

-

-
-
-
Try it Yourself!
-

Coming Soon!

-

Keep an eye out for new additions!

-
-
-
More Information
-

Check out the following links for more information!

- -
-
- - - -``` - -```css -* { - background-color: #3a3240; -} -a { - color: #92869c; -} -a:hover { - background-color: #92869c; - color: #3a3240; -} -#navbar { - border-style: solid; - border-width: 5px; - border-color: #92869c; - height: 100%; - top: -5px; - left: -5px; - padding: 5px; - text-align: center; - color: #92869c -} -@media (min-width: 480px) { - #navbar { - position: fixed; - } -} -main { - margin-left: 220px; - color: #92869c -} -header { - font-size: 20pt; -} -code { - background-color: #92869c; - border-style: dashed; - border-width: 2px; - border-color: #92869c; - padding: 5px; - color: black; -} -footer { - text-align: center; -} -``` diff --git a/curriculum/challenges/english/01-responsive-web-design/responsive-web-design-projects/build-a-tribute-page.md b/curriculum/challenges/english/01-responsive-web-design/responsive-web-design-projects/build-a-tribute-page.md deleted file mode 100644 index 7bfb1206656..00000000000 --- a/curriculum/challenges/english/01-responsive-web-design/responsive-web-design-projects/build-a-tribute-page.md +++ /dev/null @@ -1,325 +0,0 @@ ---- -id: bd7158d8c442eddfaeb5bd18 -title: Build a Tribute Page -challengeType: 14 -forumTopicId: 301147 -dashedName: build-a-tribute-page ---- - -# --description-- - -**Objective:** Build an app that is functionally similar to https://tribute-page.freecodecamp.rocks - -**User Stories:** - -1. Your tribute page should have a `main` element with a corresponding `id` of `main`, which contains all other elements -1. You should see an element with an `id` of `title`, which contains a string (i.e. text), that describes the subject of the tribute page (e.g. "Dr. Norman Borlaug") -1. You should see either a `figure` or a `div` element with an `id` of `img-div` -1. Within the `#img-div` element, you should see an `img` element with a corresponding `id="image"` -1. Within the `#img-div` element, you should see an element with a corresponding `id="img-caption"` that contains textual content describing the image shown in `#img-div` -1. You should see an element with a corresponding `id="tribute-info"`, which contains textual content describing the subject of the tribute page -1. You should see an `a` element with a corresponding `id="tribute-link"`, which links to an outside site, that contains additional information about the subject of the tribute page. HINT: You must give your element an attribute of `target` and set it to `_blank` in order for your link to open in a new tab -1. Your `#image` should use `max-width` and `height` properties to resize responsively, relative to the width of its parent element, without exceeding its original size -1. Your `img` element should be centered within its parent element - -Fulfill the user stories and pass all the tests below to complete this project. Give it your own personal style. Happy Coding! - -**Note:** Be sure to add `` in your HTML to link your stylesheet and apply your CSS - -# --hints-- - -You should have a `main` element with an `id` of `main`. - -```js -const el = document.getElementById('main') -assert(!!el && el.tagName === 'MAIN') -``` - -Your `#img-div`, `#image`, `#img-caption`, `#tribute-info`, and `#tribute-link` should all be descendants of `#main`. - -```js -const el1 = document.querySelector('#main #img-div') -const el2 = document.querySelector('#main #image') -const el3 = document.querySelector('#main #img-caption') -const el4 = document.querySelector('#main #tribute-info') -const el5 = document.querySelector('#main #tribute-link') -assert(!!el1 & !!el2 && !!el3 && !!el4 && !!el5) -``` - -You should have an element with an `id` of `title`. - -```js -const el = document.getElementById('title') -assert(!!el) -``` - -Your `#title` should not be empty. - -```js -const el = document.getElementById('title') -assert(!!el && el.innerText.length > 0) - -``` - -You should have a `figure` or `div` element with an `id` of `img-div`. - -```js -const el = document.getElementById('img-div') -assert(!!el && (el.tagName === 'DIV' || el.tagName === 'FIGURE')) -``` - -You should have an `img` element with an `id` of `image`. - -```js -const el = document.getElementById('image') -assert(!!el && el.tagName === 'IMG') -``` - -Your `#image` should be a descendant of `#img-div`. - -```js -const el = document.querySelector('#img-div #image') -assert(!!el) -``` - -You should have a `figcaption` or `div` element with an `id` of `img-caption`. - -```js -const el = document.getElementById('img-caption') -assert(!!el && (el.tagName === 'DIV' || el.tagName === 'FIGCAPTION')) -``` - -Your `#img-caption` should be a descendant of `#img-div`. - -```js -const el = document.querySelector('#img-div #img-caption') -assert(!!el) -``` - -Your `#img-caption` should not be empty. - -```js -const el = document.getElementById('img-caption') -assert(!!el && el.innerText.length > 0) -``` - -You should have an element with an `id` of `tribute-info`. - -```js -const el = document.getElementById('tribute-info') -assert(!!el) -``` - -Your `#tribute-info` should not be empty. - -```js -const el = document.getElementById('tribute-info') -assert(!!el && el.innerText.length > 0) -``` - -You should have an `a` element with an `id` of `tribute-link`. - -```js -const el = document.getElementById('tribute-link') -assert(!!el && el.tagName === 'A') -``` - -Your `#tribute-link` should have an `href` attribute and value. - -```js -const el = document.getElementById('tribute-link') -assert(!!el && !!el.href && el.href.length > 0) -``` - -Your `#tribute-link` should have a `target` attribute set to `_blank`. - -```js -const el = document.getElementById('tribute-link') -assert(!!el && el.target === '_blank') -``` - -Your `img` element should have a `display` of `block`. - -```js -const img = document.getElementById('image'); -const imgStyle = window.getComputedStyle(img); -const style = imgStyle?.getPropertyValue('display') -assert(style === 'block') -``` - -Your `#image` should have a `max-width` of `100%`. - -```js -const img = document.getElementById('image'); -const imgStyle = window.getComputedStyle(img); -const style = imgStyle?.getPropertyValue('max-width') -assert(style === '100%') -``` - -Your `#image` should have a `height` of `auto`. - -```js -// taken from the testable-projects repo -const img = document.getElementById('image'); -const imgStyle = window.getComputedStyle(img); -const oldDisplayValue = imgStyle.getPropertyValue('display'); -const oldDisplayPriority = imgStyle.getPropertyPriority('display'); -img?.style.setProperty('display', 'none', 'important'); -const heightValue = imgStyle?.getPropertyValue('height') -img?.style.setProperty('display', oldDisplayValue, oldDisplayPriority); -assert(heightValue === 'auto') -``` - -Your `#image` should be centered within its parent. - -```js -// taken from the testable-projects repo -const img = document.getElementById('image'), - imgParent = img?.parentElement, - imgLeft = img?.getBoundingClientRect().left, - imgRight = img?.getBoundingClientRect().right, - parentLeft = imgParent?.getBoundingClientRect().left, - parentRight = imgParent?.getBoundingClientRect().right, - leftMargin = imgLeft - parentLeft, - rightMargin = parentRight - imgRight; -assert(leftMargin - rightMargin < 6 && rightMargin - leftMargin < 6) -``` - -# --seed-- - -## --seed-contents-- - -```html - -``` - -```css - -``` - -## --solutions-- - -```html - - - - - - - - Tribute Page - - -

Tribute Page

-

The below card was designed as a tribute page for freeCodeCamp.

-
-
- An image of Togepi -
Togepi, happy as always.
-
-

Togepi

-
-
-

- Togepi was first discovered in the Johto region, when Ash Ketchum - discovered a mysterious egg. However, when the egg hatched, Togepi saw - Ash's friend Misty first and imprinted on her. Like many other - creatures, this imprinting process created a bond and Togepi views - Misty as his mother. -

-

- Togepi is a very childlike Pokemon, and is very emotionally - expressive. He demonstrates extreme levels of joy and sadness. -

-
-

Battle Information

-
    -
  • Type: Fairy
  • -
  • Evolutions: Togepi -> Togetic -> Togekiss
  • -
  • Moves: Growl, Pound, Sweet Kiss, Charm
  • -
  • Weaknesses: Poison, Steel
  • -
  • Resistances: Dragon
  • -
-

- Check out this - Bulbapedia article on Togepi - for more information on this great Pokemon. -

-
-
- - - -``` - -```css -body { - background-color: #3a3240; - color: white; -} -main { - background-color: #92869c; - font-family: Lobster; - max-width: 500px; - margin: 20px auto; - color: black; - border-radius: 50px; - box-shadow: 10px 10px rgba(0, 0, 0, 0.5); -} -h2 { - text-align: center; - font-size: 20pt; - font-family: Pacifico; -} -body { - text-align: center; - font-size: 12pt; -} -footer { - text-align: center; - font-size: 10pt; -} -.border { - border-color: black; - border-width: 5px; - border-style: solid; -} -#image { - height: auto; - display: block; - margin: auto; - max-width: 100%; - border-radius: 50%; -} -#img-caption { - font-size: 10pt; -} -a:not(#tribute-link) { - color: white; -} -hr { - border-color: black; -} -``` diff --git a/cypress/e2e/default/learn/challenges/multifile-cert-project.ts b/cypress/e2e/default/learn/challenges/multifile-cert-project.ts index 34227e5d4f2..afb074cdc51 100644 --- a/cypress/e2e/default/learn/challenges/multifile-cert-project.ts +++ b/cypress/e2e/default/learn/challenges/multifile-cert-project.ts @@ -17,7 +17,7 @@ describe('multifileCertProjects', function () { beforeEach(() => { cy.preserveSession(); cy.visit( - 'learn/responsive-web-design/responsive-web-design-projects/build-a-tribute-page' + 'learn/2022/responsive-web-design/build-a-tribute-page-project/build-a-tribute-page' ); }); @@ -48,9 +48,7 @@ describe('multifileCertProjects', function () { cy.contains('Your code was saved to the database.'); cy.get(editorElements.closeFlash).click(); // load saved code when navigating site (no hard refresh)' - cy.contains('Responsive Web Design Projects').click(); - cy.contains('In this Responsive Web Design Certification'); - cy.contains('Build a Tribute Page').click(); + cy.contains('Tribute Page').click(); cy.get(editorElements.container) .find(editorElements.editor) .contains(save2text); diff --git a/cypress/e2e/default/learn/index.ts b/cypress/e2e/default/learn/index.ts index f54ba2c5cbd..46036deec47 100644 --- a/cypress/e2e/default/learn/index.ts +++ b/cypress/e2e/default/learn/index.ts @@ -21,7 +21,7 @@ const superBlockNames = [ 'College Algebra with Python Certification', 'Coding Interview Prep', 'Project Euler', - 'Legacy Responsive Web Design Certification' + 'Legacy Responsive Web Design Challenges' ]; describe('Learn Landing page (not logged in)', () => { diff --git a/cypress/e2e/default/legacy/redirects/challenges.ts b/cypress/e2e/default/legacy/redirects/challenges.ts index 25e17287699..154efda8878 100644 --- a/cypress/e2e/default/legacy/redirects/challenges.ts +++ b/cypress/e2e/default/legacy/redirects/challenges.ts @@ -17,7 +17,7 @@ describe('challenges/superblock redirect', function () { cy.title().should( 'eq', - 'Legacy Responsive Web Design Certification | freeCodeCamp.org' + 'Legacy Responsive Web Design Challenges | freeCodeCamp.org' ); cy.location().should(loc => { expect(loc.pathname).to.eq(testLocations.learnSuper);