Feat: add new Markdown parser (#39800)

and change all the challenges to new `md` format.
This commit is contained in:
Oliver Eyton-Williams
2020-11-27 19:02:05 +01:00
committed by GitHub
parent a07f84c8ec
commit 0bd52f8bd1
2580 changed files with 113436 additions and 111979 deletions

View File

@@ -4,49 +4,55 @@ title: Part 1
challengeType: 0
---
## Description
<section id='description'>
# --description--
HTML elements have opening tags like `<h1>` and closing tags like `</h1>`.
Find the `h1` element and change the text between its opening and closing tags to say `CatPhotoApp`.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: The text `CatPhotoApp` should be present in the code. You may want to check your spelling.
testString: assert( code.match(/catphotoapp/i) );
- text: 'Your `h1` element should have an opening tag. Opening tags have this syntax: `<elementName>`.'
testString: assert( document.querySelector('h1') );
- text: Your `h1` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/h1\>/) );
- text: You have more than one `h1` element. Remove the extra `h1` element.
testString: assert( document.querySelectorAll('h1').length === 1 );
- text: Your `h1` element's text should be `CatPhotoApp`. You have either omitted the text, have a typo, or it is not between the `h1` element's opening and closing tags.
testString: assert( document.querySelector('h1').innerText.toLowerCase() === 'catphotoapp' );
The text `CatPhotoApp` should be present in the code. You may want to check your spelling.
```js
assert(code.match(/catphotoapp/i));
```
</section>
Your `h1` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
## Challenge Seed
<section id='challengeSeed'>
```js
assert(document.querySelector('h1'));
```
<div id='html-seed'>
Your `h1` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/h1\>/));
```
You have more than one `h1` element. Remove the extra `h1` element.
```js
assert(document.querySelectorAll('h1').length === 1);
```
Your `h1` element's text should be `CatPhotoApp`. You have either omitted the text, have a typo, or it is not between the `h1` element's opening and closing tags.
```js
assert(document.querySelector('h1').innerText.toLowerCase() === 'catphotoapp');
```
# --seed--
## --seed-contents--
```html
<html>
<body>
--fcc-editable-region--
--fcc-editable-region--
<h1>Hello World</h1>
--fcc-editable-region--
--fcc-editable-region--
</body>
</html>
```
</div>
</section>

View File

@@ -4,55 +4,78 @@ title: Part 2
challengeType: 0
---
## Description
<section id='description'>
# --description--
The `h1` to `h6` heading elements are used to signify the importance of content below them. The lower the number, the higher the importance, so `h2` elements have less importance than `h1` elements. Only use one `h1` element per page and place lower importance headings below higher importance headings.
Add an `h2` element below the `h1` element that says `Cat Photos`.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: 'Your `h1` element should have an opening tag. Opening tags have this syntax: `<elementName>`.'
testString: assert( document.querySelector('h1') );
- text: Your `h1` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/h1\>/) );
- text: You should only have one `h1` element. Remove the extra.
testString: assert( document.querySelector('h1') && document.querySelectorAll('h1').length === 1 );
- text: Your `h1` element's text should be 'CatPhotoApp'. You have either omitted the text or have a typo.
testString: assert( document.querySelector('h1').innerText.toLowerCase() === 'catphotoapp' );
- text: "Your `h2` element should have an opening tag. Opening tags have this syntax: `<elementName>`."
testString: assert( document.querySelector('h2') );
- text: Your `h2` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/h2\>/) );
- text: Your `h2` element's text should be 'Cat Photos'. Only place the text `Cat Photos` between the opening and closing `h2` tags.
testString: assert( document.querySelector('h2').innerText.toLowerCase() === 'cat photos' );
- text: "Your `h2` element should be below the `h1` element. The `h1` element has greater importance and must be above the `h2` element."
testString: const collection = [...document.querySelectorAll('h1,h2')].map(node => node.nodeName); assert( collection.indexOf('H1') < collection.indexOf('H2') );
Your `h1` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('h1'));
```
</section>
Your `h1` element should have a closing tag. Closing tags have a `/` just after the `<` character.
## Challenge Seed
<section id='challengeSeed'>
```js
assert(code.match(/<\/h1\>/));
```
<div id='html-seed'>
You should only have one `h1` element. Remove the extra.
```js
assert(
document.querySelector('h1') && document.querySelectorAll('h1').length === 1
);
```
Your `h1` element's text should be 'CatPhotoApp'. You have either omitted the text or have a typo.
```js
assert(document.querySelector('h1').innerText.toLowerCase() === 'catphotoapp');
```
Your `h2` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('h2'));
```
Your `h2` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/h2\>/));
```
Your `h2` element's text should be 'Cat Photos'. Only place the text `Cat Photos` between the opening and closing `h2` tags.
```js
assert(document.querySelector('h2').innerText.toLowerCase() === 'cat photos');
```
Your `h2` element should be below the `h1` element. The `h1` element has greater importance and must be above the `h2` element.
```js
const collection = [...document.querySelectorAll('h1,h2')].map(
(node) => node.nodeName
);
assert(collection.indexOf('H1') < collection.indexOf('H2'));
```
# --seed--
## --seed-contents--
```html
<html>
<body>
--fcc-editable-region--
--fcc-editable-region--
<h1>CatPhotoApp</h1>
--fcc-editable-region--
--fcc-editable-region--
</body>
</html>
```
</div>
</section>

View File

@@ -4,48 +4,56 @@ title: Part 3
challengeType: 0
---
## Description
<section id='description'>
# --description--
Paragraph (`p`) elements are used to create paragraph text on websites.
Paragraph (`p`) elements are used to create paragraph text on websites.
Create a paragraph (`p`) element below your `h2` element, and give it the text `Click here to view more cat photos.`
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: "Your `p` element should have an opening tag. Opening tags have the following syntax: `<elementName>`."
testString: assert( document.querySelector('p') );
- text: Your `p` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/p\>/) );
- text: Your `p` element's text should be `Click here to view more cat photos.` You have either omitted the text or have a typo.
testString: const extraSpacesRemoved = document.querySelector('p').innerText.replace(/\s+/g, ' '); assert( extraSpacesRemoved.match(/click here to view more cat photos\.?$/i) );
- text: Your `p` element should be below the `h2` element. You have them in the wrong order.
testString: const collection = [...document.querySelectorAll('h2,p')].map(node => node.nodeName); assert( collection.indexOf('H2') < collection.indexOf('P') );
Your `p` element should have an opening tag. Opening tags have the following syntax: `<elementName>`.
```js
assert(document.querySelector('p'));
```
</section>
Your `p` element should have a closing tag. Closing tags have a `/` just after the `<` character.
## Challenge Seed
<section id='challengeSeed'>
```js
assert(code.match(/<\/p\>/));
```
<div id='html-seed'>
Your `p` element's text should be `Click here to view more cat photos.` You have either omitted the text or have a typo.
```js
const extraSpacesRemoved = document
.querySelector('p')
.innerText.replace(/\s+/g, ' ');
assert(extraSpacesRemoved.match(/click here to view more cat photos\.?$/i));
```
Your `p` element should be below the `h2` element. You have them in the wrong order.
```js
const collection = [...document.querySelectorAll('h2,p')].map(
(node) => node.nodeName
);
assert(collection.indexOf('H2') < collection.indexOf('P'));
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<h1>CatPhotoApp</h1>
--fcc-editable-region--
--fcc-editable-region--
<h2>Cat Photos</h2>
--fcc-editable-region--
--fcc-editable-region--
</body>
</html>
```
</div>
</section>

View File

@@ -4,53 +4,64 @@ title: Part 4
challengeType: 0
---
## Description
<section id='description'>
# --description--
Commenting allows you to leave messages without affecting the browser display. It also allows you to make code inactive. A comment in HTML starts with `<!--`, contains any number of lines of text, and ends with `-->`. For example, the comment `<!-- TODO: Remove h1 -->` contains the text `TODO: Remove h1`.
Add a comment above the `p` element with the text `TODO: Add link to cat photos`. \
Add a comment above the `p` element with the text `TODO: Add link to cat photos`. \\
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: Your comment should start with `<!--`. You are missing one or more of the characters that define the start of a comment.
testString: assert( code.match(/<!--/) );
- text: Your comment should end with `-->`. You are missing one or more of the characters that define the end of a comment.
testString: assert( code.match(/-->/) );
- text: Your code should not have extra opening/closing comment characters. You have an extra `<!--` or `-->` displaying in the browser.
testString: |
const noSpaces = code.replace(/\s/g, '');
assert (noSpaces.match(/<!--/g).length < 2 && noSpaces.match(/-->/g).length < 2 );
- text: 'Your comment should contain the text `TODO: Add link to cat photos`.'
testString: assert( code.match(/<!--\s*todo:\s+add\s+link\s+to\s+cat\s+photos\s*-->/i) );
- text: Your comment should be above the `p` element. You have them in the wrong order.
testString: assert( code.replace(/\s/g, '').match(/<!--todo:addlinktocatphotos--><p>clickheretoviewmorecatphotos\.?<\/p>/i) );
Your comment should start with `<!--`. You are missing one or more of the characters that define the start of a comment.
```js
assert(code.match(/<!--/));
```
</section>
Your comment should end with `-->`. You are missing one or more of the characters that define the end of a comment.
## Challenge Seed
<section id='challengeSeed'>
```js
assert(code.match(/-->/));
```
<div id='html-seed'>
Your code should not have extra opening/closing comment characters. You have an extra `<!--` or `-->` displaying in the browser.
```js
const noSpaces = code.replace(/\s/g, '');
assert(noSpaces.match(/<!--/g).length < 2 && noSpaces.match(/-->/g).length < 2);
```
Your comment should contain the text `TODO: Add link to cat photos`.
```js
assert(code.match(/<!--\s*todo:\s+add\s+link\s+to\s+cat\s+photos\s*-->/i));
```
Your comment should be above the `p` element. You have them in the wrong order.
```js
assert(
code
.replace(/\s/g, '')
.match(
/<!--todo:addlinktocatphotos--><p>clickheretoviewmorecatphotos\.?<\/p>/i
)
);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<h1>CatPhotoApp</h1>
<h2>Cat Photos</h2>
--fcc-editable-region--
--fcc-editable-region--
<p>Click here to view more cat photos.</p>
--fcc-editable-region--
--fcc-editable-region--
</body>
</html>
```
</div>
</section>

View File

@@ -4,52 +4,69 @@ title: Part 5
challengeType: 0
---
## Description
<section id='description'>
# --description--
HTML5 has some elements that identify different content areas. These elements make your HTML easier to read and help with Search Engine Optimization (SEO) and accessibility.
Identify the main section of this page by adding a `<main>` opening tag after the `h1` element, and a `</main>` closing tag after the `p` element.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: "Your `main` element should have an opening tag. Opening tags have this syntax: `<elementName>`."
testString: assert( document.querySelector('main') );
- text: Your `main` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/main\>/) );
- text: Your `main` element's opening tag should be below the `h1` element. You have them in the wrong order.
testString: const collection = [...document.querySelectorAll('main,h1')].map(node => node.nodeName); assert( collection.indexOf('H1') < collection.indexOf('MAIN') );
- text: Your `main` element's opening tag should be above the `h2` element. You have them in the wrong order.
testString: const collection = [...document.querySelectorAll('main,h2')].map(node => node.nodeName); assert( collection.indexOf('MAIN') < collection.indexOf('H2') );
- text: Your `main` element's closing tag should be below the `p` element. You have them in the wrong order.
testString: const mainNode = document.querySelector('main'); const pNode = document.querySelector('p'); assert( mainNode.contains(pNode) && pNode.textContent.toLowerCase().match(/click here to view more cat photos/) );
Your `main` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('main'));
```
</section>
Your `main` element should have a closing tag. Closing tags have a `/` just after the `<` character.
## Challenge Seed
<section id='challengeSeed'>
```js
assert(code.match(/<\/main\>/));
```
<div id='html-seed'>
Your `main` element's opening tag should be below the `h1` element. You have them in the wrong order.
```js
const collection = [...document.querySelectorAll('main,h1')].map(
(node) => node.nodeName
);
assert(collection.indexOf('H1') < collection.indexOf('MAIN'));
```
Your `main` element's opening tag should be above the `h2` element. You have them in the wrong order.
```js
const collection = [...document.querySelectorAll('main,h2')].map(
(node) => node.nodeName
);
assert(collection.indexOf('MAIN') < collection.indexOf('H2'));
```
Your `main` element's closing tag should be below the `p` element. You have them in the wrong order.
```js
const mainNode = document.querySelector('main');
const pNode = document.querySelector('p');
assert(
mainNode.contains(pNode) &&
pNode.textContent.toLowerCase().match(/click here to view more cat photos/)
);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
--fcc-editable-region--
--fcc-editable-region--
<h1>CatPhotoApp</h1>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>Click here to view more cat photos.</p>
--fcc-editable-region--
--fcc-editable-region--
</body>
</html>
```
</div>
</section>

View File

@@ -4,60 +4,91 @@ title: Part 6
challengeType: 0
---
## Description
<section id='description'>
# --description--
HTML elements are often nested within other HTML elements. In the previous step you nested the `h2` element, comment and `p` element within the `main` element. A nested element is a child of its parent element.
To make HTML easier to read, indent the `h2` element, the comment, and `p` element exactly two spaces to indicate they are children of the `main` element.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: Your should have an `h2` element with text `Cat Photos`. You may have accidentally deleted it, it is missing both opening and closing tags, or the text has changed.
testString: assert( document.querySelector('h2') && code.match(/<\/h2\>/) && document.querySelector('h2').innerText.toLowerCase() === 'cat photos' );
- text: Your `h2` element should below the `main` element's opening tag and its opening tag should start 6 spaces over from the start of the line.
testString: assert( code.toLowerCase().match(/<main\>\n\s{6}<h2>/) );
- text: Your code should have a comment. You removed the comment from an earlier step.
testString: assert( code.match(/<!--.*-->/) );
- text: "The comment's text should be `TODO: Add link to cat photos`. Do not change the text or spacing of the comment."
testString: 'assert( code.match(/<!--\s*todo:\s+add\s+link\s+to\s+cat\s+photos\.?\s*-->/i) );'
- text: Your comment should be below the `h2` element and start 6 spaces over from the start of the line.
testString: 'assert( code.toLowerCase().match(/<\/h2>\n\s{6}<!--\s*todo:\s+add\s+link\s+to\s+cat\s+photos\s*-->/) );'
- text: Your code should have a `p` element. You have removed the `p` element from an earlier step.
testString: assert( document.querySelector('p') );
- text: The text of the `p` element should be `Click here to view more cat photos.` Do not change the text, spacing, or punctuation of the `p` element.
testString: assert( document.querySelector('p').innerText.toLowerCase().match(/click\s+here\s+to\s+view\s+more\s+cat\s+photos\.?$/) );
- text: Your `p` element should be below the comment and its opening tag should start 6 spaces over from the start of the line.
testString: assert( code.toLowerCase().match(/-->\n\s{6}<p>/) );
Your should have an `h2` element with text `Cat Photos`. You may have accidentally deleted it, it is missing both opening and closing tags, or the text has changed.
```js
assert(
document.querySelector('h2') &&
code.match(/<\/h2\>/) &&
document.querySelector('h2').innerText.toLowerCase() === 'cat photos'
);
```
</section>
Your `h2` element should below the `main` element's opening tag and its opening tag should start 6 spaces over from the start of the line.
## Challenge Seed
<section id='challengeSeed'>
```js
assert(code.toLowerCase().match(/<main\>\n\s{6}<h2>/));
```
<div id='html-seed'>
Your code should have a comment. You removed the comment from an earlier step.
```js
assert(code.match(/<!--.*-->/));
```
The comment's text should be `TODO: Add link to cat photos`. Do not change the text or spacing of the comment.
```js
assert(code.match(/<!--\s*todo:\s+add\s+link\s+to\s+cat\s+photos\.?\s*-->/i));
```
Your comment should be below the `h2` element and start 6 spaces over from the start of the line.
```js
assert(
code
.toLowerCase()
.match(/<\/h2>\n\s{6}<!--\s*todo:\s+add\s+link\s+to\s+cat\s+photos\s*-->/)
);
```
Your code should have a `p` element. You have removed the `p` element from an earlier step.
```js
assert(document.querySelector('p'));
```
The text of the `p` element should be `Click here to view more cat photos.` Do not change the text, spacing, or punctuation of the `p` element.
```js
assert(
document
.querySelector('p')
.innerText.toLowerCase()
.match(/click\s+here\s+to\s+view\s+more\s+cat\s+photos\.?$/)
);
```
Your `p` element should be below the comment and its opening tag should start 6 spaces over from the start of the line.
```js
assert(code.toLowerCase().match(/-->\n\s{6}<p>/));
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<h1>CatPhotoApp</h1>
<main>
--fcc-editable-region--
--fcc-editable-region--
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>Click here to view more cat photos.</p>
--fcc-editable-region--
--fcc-editable-region--
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,37 +4,44 @@ title: Part 7
challengeType: 0
---
## Description
<section id='description'>
# --description--
You can add images to your website by using the `img` element. `img` elements have an opening tag without a closing tag. A tag for an element without a closing tag is known as a <dfn>self-closing tag</dfn>.
You can add images to your website by using the `img` element. `img` elements have an opening tag without a closing tag. A tag for an element without a closing tag is known as a <dfn>self-closing tag</dfn>.
Add an `img` element below the `p` element. At this point, no image will show up in the browser.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: "Your `img` element should have an opening tag. Opening tags have this syntax: `<elementName>`."
testString: assert( document.querySelector('img') );
- text: Your `img` element should not have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( !code.match(/<\/img\>/) );
- text: You should only have one `img` element. Remove any extras.
testString: assert( document.querySelectorAll('img').length === 1 );
- text: Your `img` element should be below the `p` element. You have them in the wrong order.
testString: const collection = [...document.querySelectorAll('p,img')].map(node => node.nodeName); assert( collection.indexOf('P') < collection.indexOf('IMG') );
Your `img` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('img'));
```
</section>
Your `img` element should not have a closing tag. Closing tags have a `/` just after the `<` character.
## Challenge Seed
<section id='challengeSeed'>
```js
assert(!code.match(/<\/img\>/));
```
<div id='html-seed'>
You should only have one `img` element. Remove any extras.
```js
assert(document.querySelectorAll('img').length === 1);
```
Your `img` element should be below the `p` element. You have them in the wrong order.
```js
const collection = [...document.querySelectorAll('p,img')].map(
(node) => node.nodeName
);
assert(collection.indexOf('P') < collection.indexOf('IMG'));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -43,13 +50,11 @@ tests:
<main>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
--fcc-editable-region--
--fcc-editable-region--
<p>Click here to view more cat photos.</p>
--fcc-editable-region--
--fcc-editable-region--
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,37 +4,41 @@ title: Part 8
challengeType: 0
---
## Description
<section id='description'>
# --description--
HTML <dfn>attributes</dfn> are special words used inside the opening tag of an element to control the element's behavior. The `src` attribute in an `img` element specifies the image's URL (where the image is located). An example of an `img` element using an `src` attribute: `<img src="https://www.your-image-source.com/your-image.jpg">`.
Add an `src` attribute to the existing `img` element that is set to the following URL: `https://bit.ly/fcc-relaxing-cat`.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: Your code should have an `img` element. You may have removed the `img` element or you have not surrounded the `src` attribute's value with quotes.
testString: assert( document.querySelector('img') );
- text: Your `img` element should have an `src` attribute. You have either omitted the attribute or have a typo. Make sure there is a space between the element name and the attribute name.
testString: assert( document.querySelector('img').src );
- text: Your `img` element's `src` attribute should be set to 'https://bit.ly/fcc-relaxing-cat'. You have either omitted the URL or have a typo. The case of the URL is important.
testString: assert( document.querySelector('img').src === 'https://bit.ly/fcc-relaxing-cat' );
- text: Although you have set the `img` element's `src` to the correct URL, it is recommended to always surround the value of an attribute with quotation marks.
testString: assert( !/\<img\s+src\s*=\s*https:\/\/bit\.ly\/fcc-relaxing-cat/.test(code) );
Your code should have an `img` element. You may have removed the `img` element or you have not surrounded the `src` attribute's value with quotes.
```js
assert(document.querySelector('img'));
```
</section>
Your `img` element should have an `src` attribute. You have either omitted the attribute or have a typo. Make sure there is a space between the element name and the attribute name.
## Challenge Seed
<section id='challengeSeed'>
```js
assert(document.querySelector('img').src);
```
<div id='html-seed'>
Your `img` element's `src` attribute should be set to '`https://bit.ly/fcc-relaxing-cat`'. You have either omitted the URL or have a typo. The case of the URL is important.
```js
assert(document.querySelector('img').src === 'https://bit.ly/fcc-relaxing-cat');
```
Although you have set the `img` element's `src` to the correct URL, it is recommended to always surround the value of an attribute with quotation marks.
```js
assert(!/\<img\s+src\s*=\s*https:\/\/bit\.ly\/fcc-relaxing-cat/.test(code));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -44,13 +48,11 @@ tests:
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>Click here to view more cat photos.</p>
--fcc-editable-region--
--fcc-editable-region--
<img>
--fcc-editable-region--
--fcc-editable-region--
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,36 +4,39 @@ title: Part 9
challengeType: 0
---
## Description
<section id='description'>
# --description--
All `img` elements should have an `alt` attribute. The `alt` attribute's text is used for screen readers to improve accessibility and is displayed if the image fails to load. For example, `<img src="cat.jpg" alt="A cat">` has an `alt` attribute with the text `A cat`.
All `img` elements should have an `alt` attribute. The `alt` attribute's text is used for screen readers to improve accessibility and is displayed if the image fails to load. For example, `<img src="cat.jpg" alt="A cat">` has an `alt` attribute with the text `A cat`.
Add an `alt` attribute to the `img` element with the text `A cute orange cat lying on its back`.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: Your code should have an `img` element. You removed the `img` element from an earlier step.
testString: assert( document.querySelector('img') );
- text: Your `img` element does not have an `alt` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
testString: assert( document.querySelector('img').hasAttribute('alt') );
- text: Your `img` element's `alt` attribute value is set to something other than 'A cute orange cat lying on its back'. Make sure the `alt` attribute's value is surrounded with quotation marks.
testString: const altText = document.querySelector('img').alt.toLowerCase().replace(/\s+/g, ' '); assert( altText.match(/A cute orange cat lying on its back\.?$/i) );
Your code should have an `img` element. You removed the `img` element from an earlier step.
```js
assert(document.querySelector('img'));
```
</section>
Your `img` element does not have an `alt` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
## Challenge Seed
<section id='challengeSeed'>
```js
assert(document.querySelector('img').hasAttribute('alt'));
```
<div id='html-seed'>
Your `img` element's `alt` attribute value is set to something other than 'A cute orange cat lying on its back'. Make sure the `alt` attribute's value is surrounded with quotation marks.
```js
const altText = document
.querySelector('img')
.alt.toLowerCase()
.replace(/\s+/g, ' ');
assert(altText.match(/A cute orange cat lying on its back\.?$/i));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -43,13 +46,11 @@ tests:
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>Click here to view more cat photos.</p>
--fcc-editable-region--
--fcc-editable-region--
<img src="https://bit.ly/fcc-relaxing-cat">
--fcc-editable-region--
--fcc-editable-region--
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,41 +4,61 @@ title: Part 10
challengeType: 0
---
## Description
<section id='description'>
# --description--
You can link to another page with the anchor (`a`) element. For example, <a href="https://www.freecodecamp.org"></a> would link to `freecodecamp.org`.
You can link to another page with the anchor (`a`) element. For example, [](https://www.freecodecamp.org) would link to `freecodecamp.org`.
Add an anchor element after the paragraph that links to `https://freecatphotoapp.com`. At this point, the link wont show up in the preview.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: "Your anchor (`a`) element should have an opening tag. Opening tags have this syntax: `<elementName>`."
testString: assert( document.querySelector('a') );
- text: "Your anchor (`a`) element should have a closing tag. Closing tags have a `/` just after the `<` character."
testString: assert( code.match(/<\/a\>/) );
- text: "Your anchor (`a`) element should be below the `p` element. You have them in the wrong order."
testString: const collection = [...document.querySelectorAll('a, p')].map(node => node.nodeName); assert( collection.indexOf('P') < collection.indexOf('A') );
- text: Your anchor (`a`) element does not have an `href` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
testString: assert( document.querySelector('a').hasAttribute('href') );
- text: "Your anchor (`a`) element should link to `https://freecatphotoapp.com`. You have either omitted the URL or have a typo."
testString: assert( document.querySelector('a').getAttribute('href') === 'https://freecatphotoapp.com' );
- text: Although you have set the anchor ('a') element's `href` attribute to the correct link, it is recommended to always surround the value of an attribute with quotation marks.
testString: assert( !/\<a\s+href\s*=\s*https:\/\/www.freecodecamp.org\/cat-photos/.test(code) );
Your anchor (`a`) element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('a'));
```
</section>
Your anchor (`a`) element should have a closing tag. Closing tags have a `/` just after the `<` character.
## Challenge Seed
<section id='challengeSeed'>
```js
assert(code.match(/<\/a\>/));
```
<div id='html-seed'>
Your anchor (`a`) element should be below the `p` element. You have them in the wrong order.
```js
const collection = [...document.querySelectorAll('a, p')].map(
(node) => node.nodeName
);
assert(collection.indexOf('P') < collection.indexOf('A'));
```
Your anchor (`a`) element does not have an `href` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
```js
assert(document.querySelector('a').hasAttribute('href'));
```
Your anchor (`a`) element should link to `https://freecatphotoapp.com`. You have either omitted the URL or have a typo.
```js
assert(
document.querySelector('a').getAttribute('href') ===
'https://freecatphotoapp.com'
);
```
Although you have set the anchor ('a') element's `href` attribute to the correct link, it is recommended to always surround the value of an attribute with quotation marks.
```js
assert(
!/\<a\s+href\s*=\s*https:\/\/www.freecodecamp.org\/cat-photos/.test(code)
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -47,14 +67,12 @@ tests:
<main>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
--fcc-editable-region--
--fcc-editable-region--
<p>Click here to view more cat photos.</p>
--fcc-editable-region--
--fcc-editable-region--
<img src="https://bit.ly/fcc-relaxing-cat" alt="A cute orange cat lying on its back.">
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,35 +4,38 @@ title: Part 11
challengeType: 0
---
## Description
<section id='description'>
# --description--
A link's text must be placed between the opening and closing tags of an anchor (`a`) element. For example, `<a href="https://www.freecodecamp.org">click here to go to freeCodeCamp.org</a>` is a link with the text `click here to go to freeCodeCamp.org`.
Add the anchor text `cat photos` to the anchor element. This will become the link's text.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: "Your anchor (`a`) element should have an opening tag. Opening tags have this syntax: `<elementName>`."
testString: assert( document.querySelector('a') );
- text: "Your anchor (`a`) element should have a closing tag. Closing tags have a `/` just after the `<` character."
testString: assert( code.match(/<\/a\>/) );
- text: Your anchor (`a`) element's text should be `cat photos`. Make sure to put the link text between the anchor (`a`) element's opening tag and closing tag.
testString: assert( document.querySelector('a').innerText.toLowerCase().replace(/\s+/g, ' ') === 'cat photos' );
Your anchor (`a`) element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('a'));
```
</section>
Your anchor (`a`) element should have a closing tag. Closing tags have a `/` just after the `<` character.
## Challenge Seed
<section id='challengeSeed'>
```js
assert(code.match(/<\/a\>/));
```
<div id='html-seed'>
Your anchor (`a`) element's text should be `cat photos`. Make sure to put the link text between the anchor (`a`) element's opening tag and closing tag.
```js
assert(
document.querySelector('a').innerText.toLowerCase().replace(/\s+/g, ' ') ===
'cat photos'
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -42,14 +45,12 @@ tests:
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>Click here to view more cat photos.</p>
--fcc-editable-region--
--fcc-editable-region--
<a href="https://freecatphotoapp.com"></a>
--fcc-editable-region--
--fcc-editable-region--
<img src="https://bit.ly/fcc-relaxing-cat" alt="A cute orange cat lying on its back.">
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,41 +4,47 @@ title: Part 12
challengeType: 0
---
## Description
<section id='description'>
# --description--
Turn the words `cat photos` located inside `p` element into a link by replacing the words with the anchor element added previously. The `p` element should show the same text in the browser, but the words `cat photos` should now be a link. There should only be one link showing in the app.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: Your code should only contain one anchor (`a`) element. Remove any extra anchor elements.
testString: assert( document.querySelectorAll('a').length === 1 );
- text: Your anchor (`a`) element should be nested within the `p` element.
testString: assert( $('p > a').length);
- text: The link's text should be `cat photos`. You have either omitted the text or have a typo.
testString: const nestedAnchor = $('p > a')[0];
assert(
nestedAnchor.getAttribute('href') === 'https://freecatphotoapp.com' &&
nestedAnchor.innerText.toLowerCase().replace(/\s+/g, ' ') === 'cat photos'
);
- text: After nesting the anchor (`a`) element, the only `p` element content visible in the browser should be `Click here to view more cat photos.` Double check the text, spacing, or punctuation of both the `p` and nested anchor element.
testString: |
const pText = document.querySelector('p').innerText.toLowerCase().replace(/\s+/g, ' ');
assert( pText.match(/click here to view more cat photos\.?$/) );
Your code should only contain one anchor (`a`) element. Remove any extra anchor elements.
```js
assert(document.querySelectorAll('a').length === 1);
```
</section>
Your anchor (`a`) element should be nested within the `p` element.
## Challenge Seed
<section id='challengeSeed'>
```js
assert($('p > a').length);
```
<div id='html-seed'>
The link's text should be `cat photos`. You have either omitted the text or have a typo.
```js
const nestedAnchor = $('p > a')[0];
assert(
nestedAnchor.getAttribute('href') === 'https://freecatphotoapp.com' &&
nestedAnchor.innerText.toLowerCase().replace(/\s+/g, ' ') === 'cat photos'
);
```
After nesting the anchor (`a`) element, the only `p` element content visible in the browser should be `Click here to view more cat photos.` Double check the text, spacing, or punctuation of both the `p` and nested anchor element.
```js
const pText = document
.querySelector('p')
.innerText.toLowerCase()
.replace(/\s+/g, ' ');
assert(pText.match(/click here to view more cat photos\.?$/));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -47,15 +53,13 @@ tests:
<main>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
--fcc-editable-region--
--fcc-editable-region--
<p>Click here to view more cat photos.</p>
<a href="https://freecatphotoapp.com">cat photos</a>
--fcc-editable-region--
--fcc-editable-region--
<img src="https://bit.ly/fcc-relaxing-cat" alt="A cute orange cat lying on its back.">
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,35 +4,37 @@ title: Part 13
challengeType: 0
---
## Description
<section id='description'>
# --description--
Add a `target` attribute with the value `_blank` to the anchor (`a`) element's opening tag, so that the link opens in a new tab.
Add a `target` attribute with the value `_blank` to the anchor (`a`) element's opening tag, so that the link opens in a new tab.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: Your `p` element should have a nested anchor (`a`) element with the text `cat photos`. You may have deleted it or have a typo.
testString: |
const anchor = $('p > a');
assert(anchor.length && anchor[0].innerText.toLowerCase().replace(/\s+/g, ' ') === 'cat photos');
- text: Your anchor (`a`) element does not have a `target` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
testString: assert( document.querySelector('a').hasAttribute('target') );
- text: The value of the `target` attribute should '_blank'. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
testString: assert( document.querySelector('a').getAttribute('target') === '_blank' );
Your `p` element should have a nested anchor (`a`) element with the text `cat photos`. You may have deleted it or have a typo.
```js
const anchor = $('p > a');
assert(
anchor.length &&
anchor[0].innerText.toLowerCase().replace(/\s+/g, ' ') === 'cat photos'
);
```
</section>
Your anchor (`a`) element does not have a `target` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
## Challenge Seed
<section id='challengeSeed'>
```js
assert(document.querySelector('a').hasAttribute('target'));
```
<div id='html-seed'>
The value of the `target` attribute should '\_blank'. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
```js
assert(document.querySelector('a').getAttribute('target') === '_blank');
```
# --seed--
## --seed-contents--
```html
<html>
@@ -41,14 +43,12 @@ tests:
<main>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
--fcc-editable-region--
--fcc-editable-region--
<p>Click here to view more <a href="https://freecatphotoapp.com">cat photos</a>.</p>
--fcc-editable-region--
--fcc-editable-region--
<img src="https://bit.ly/fcc-relaxing-cat" alt="A cute orange cat lying on its back.">
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,43 +4,70 @@ title: Part 14
challengeType: 0
---
## Description
<section id='description'>
# --description--
Turn the image into a link by surrounding it with necessary element tags. Use `https://freecatphotoapp.com` as the anchor's `href` attribute value.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: You should have an `img` element with an `src` value of `https://bit.ly/fcc-relaxing-cat`. You may have accidentally deleted it.
testString: assert( document.querySelector('img') && document.querySelector('img').getAttribute('src') === 'https://bit.ly/fcc-relaxing-cat' );
- text: "Your anchor (`a`) element should have an opening tag. Opening tags have this syntax: `<elementName>`."
testString: assert( document.querySelectorAll('a').length >= 2 );
- text: You should only add one opening anchor (`a`) tag. Please remove any extras.
testString: assert( document.querySelectorAll('a').length === 2 );
- text: Your anchor (`a`) element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/a>/g).length >= 2 );
- text: You should only add one closing anchor (`a`) tag. Please remove any extras.
testString: assert( code.match(/<\/a>/g).length === 2 );
- text: Your anchor (`a`) element does not have an `href` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
testString: assert( document.querySelector('a').hasAttribute('href') );
- text: Your anchor (`a`) element should link to `https://freecatphotoapp.com`. You have either omitted the URL or have a typo.
testString: assert( document.querySelectorAll('a')[1].getAttribute('href') === 'https://freecatphotoapp.com' );
- text: Your `img` element should be nested within the anchor (`a`) element. The entire `img` element should be inside the opening and closing tags of the anchor (`a`) element.
testString: assert( document.querySelector('img').parentNode.nodeName === "A" );
You should have an `img` element with an `src` value of `https://bit.ly/fcc-relaxing-cat`. You may have accidentally deleted it.
```js
assert(
document.querySelector('img') &&
document.querySelector('img').getAttribute('src') ===
'https://bit.ly/fcc-relaxing-cat'
);
```
</section>
Your anchor (`a`) element should have an opening tag. Opening tags have this syntax: `<elementName>`.
## Challenge Seed
<section id='challengeSeed'>
```js
assert(document.querySelectorAll('a').length >= 2);
```
<div id='html-seed'>
You should only add one opening anchor (`a`) tag. Please remove any extras.
```js
assert(document.querySelectorAll('a').length === 2);
```
Your anchor (`a`) element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/a>/g).length >= 2);
```
You should only add one closing anchor (`a`) tag. Please remove any extras.
```js
assert(code.match(/<\/a>/g).length === 2);
```
Your anchor (`a`) element does not have an `href` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
```js
assert(document.querySelector('a').hasAttribute('href'));
```
Your anchor (`a`) element should link to `https://freecatphotoapp.com`. You have either omitted the URL or have a typo.
```js
assert(
document.querySelectorAll('a')[1].getAttribute('href') ===
'https://freecatphotoapp.com'
);
```
Your `img` element should be nested within the anchor (`a`) element. The entire `img` element should be inside the opening and closing tags of the anchor (`a`) element.
```js
assert(document.querySelector('img').parentNode.nodeName === 'A');
```
# --seed--
## --seed-contents--
```html
<html>
@@ -50,13 +77,11 @@ tests:
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>Click here to view more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a>.</p>
--fcc-editable-region--
--fcc-editable-region--
<img src="https://bit.ly/fcc-relaxing-cat" alt="A cute orange cat lying on its back.">
--fcc-editable-region--
--fcc-editable-region--
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,58 +4,59 @@ title: Part 15
challengeType: 0
---
## Description
<section id='description'>
# --description--
Before adding any new content, you should make use of a `section` element to separate the cat photos content from the future content.
Take all the elements currently located within the `main` element and nest them in a `section` element.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: "Your `section` element should have an opening tag. Opening tags have the following syntax: `<elementName>`."
testString: assert( document.querySelector('section') );
- text: Your `section` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/section\>/) );
- text: The entire `section` element should be between the opening and closing tags of the `main` element.
testString: assert( document.querySelector('section').parentNode.nodeName === "MAIN" );
- text: The existing `h2`, comment, `p` element, and anchor (`a`) element should be between the opening and closing tags of the `section` element.
testString: |
const childrenOfSection = [ ...document.querySelector('section').childNodes ];
const foundElems = childrenOfSection.filter(child => {
return ['H2', 'A', 'P'].includes(child.nodeName);
});
assert( foundElems.length === 3 );
Your `section` element should have an opening tag. Opening tags have the following syntax: `<elementName>`.
```js
assert(document.querySelector('section'));
```
</section>
Your `section` element should have a closing tag. Closing tags have a `/` just after the `<` character.
## Challenge Seed
<section id='challengeSeed'>
```js
assert(code.match(/<\/section\>/));
```
<div id='html-seed'>
The entire `section` element should be between the opening and closing tags of the `main` element.
```js
assert(document.querySelector('section').parentNode.nodeName === 'MAIN');
```
The existing `h2`, comment, `p` element, and anchor (`a`) element should be between the opening and closing tags of the `section` element.
```js
const childrenOfSection = [...document.querySelector('section').childNodes];
const foundElems = childrenOfSection.filter((child) => {
return ['H2', 'A', 'P'].includes(child.nodeName);
});
assert(foundElems.length === 3);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<h1>CatPhotoApp</h1>
--fcc-editable-region--
--fcc-editable-region--
<main>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>Click here to view more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a>.</p>
<a href="https://freecatphotoapp.com"><img src="https://bit.ly/fcc-relaxing-cat" alt="A cute orange cat lying on its back."></a>
</main>
--fcc-editable-region--
--fcc-editable-region--
</body>
</html>
```
</div>
</section>

View File

@@ -4,67 +4,77 @@ title: Part 16
challengeType: 0
---
## Description
<section id='description'>
# --description--
It is time to add a new section. Add a second `section` element below the existing `section` element.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: "Your `section` element should have an opening tag. Opening tags have this syntax: `<elementName>`."
testString: assert( document.querySelectorAll('section').length >= 2 );
- text: You should only add one opening `section` tag. Please remove any extras.
testString: assert( document.querySelectorAll('section').length === 2 );
- text: Your `section` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/section>/g).length >= 2 );
- text: You should only add one closing `section` tag. Please remove any extras.
testString: assert( code.match(/<\/section>/g).length === 2 );
- text: The second `section` element should not be nested in the first `section` element.
testString: |
const childrenOf1stSection = [ ...document.querySelector('main > section').children ];
const foundElems = childrenOf1stSection.filter(child => {
return child.nodeName === 'SECTION';
});
assert( foundElems.length === 0 );
- text: Both `section` elements should be between the opening and closing tags of the `main` element.
testString: |
const childrenOfMain = [ ...document.querySelector('main').children ];
const foundElems = childrenOfMain.filter(child => {
return child.nodeName === 'SECTION';
});
assert( foundElems.length === 2 );
Your `section` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelectorAll('section').length >= 2);
```
</section>
You should only add one opening `section` tag. Please remove any extras.
## Challenge Seed
<section id='challengeSeed'>
```js
assert(document.querySelectorAll('section').length === 2);
```
<div id='html-seed'>
Your `section` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/section>/g).length >= 2);
```
You should only add one closing `section` tag. Please remove any extras.
```js
assert(code.match(/<\/section>/g).length === 2);
```
The second `section` element should not be nested in the first `section` element.
```js
const childrenOf1stSection = [
...document.querySelector('main > section').children
];
const foundElems = childrenOf1stSection.filter((child) => {
return child.nodeName === 'SECTION';
});
assert(foundElems.length === 0);
```
Both `section` elements should be between the opening and closing tags of the `main` element.
```js
const childrenOfMain = [...document.querySelector('main').children];
const foundElems = childrenOfMain.filter((child) => {
return child.nodeName === 'SECTION';
});
assert(foundElems.length === 2);
```
# --seed--
## --seed-contents--
```html
<html>
<body>
<h1>CatPhotoApp</h1>
<main>
--fcc-editable-region--
--fcc-editable-region--
<section>
<h2>Cat Photos</h2>
<!-- TODO: Add link to cat photos -->
<p>Click here to view more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a>.</p>
<a href="https://freecatphotoapp.com"><img src="https://bit.ly/fcc-relaxing-cat" alt="A cute orange cat lying on its back."></a>
</section>
--fcc-editable-region--
--fcc-editable-region--
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,43 +4,53 @@ title: Part 17
challengeType: 0
---
## Description
<section id='description'>
# --description--
Within the second `section` element, add a new `h2` element with the text `Cat Lists`.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: "Your `section` element should have an opening tag. Opening tags have this syntax: `<elementName>`."
testString: |
assert(
document.querySelectorAll('section').length === 2 &&
code.match(/<\/section>/g).length === 2
);
- text: "Your `h2` element should have an opening tag. Opening tags have this syntax: `<elementName>`."
testString: assert( document.querySelectorAll('h2').length === 2 );
- text: "Your `h2` element should have a closing tag. Closing tags have a `/` just after the `<` character."
testString: assert( code.match(/<\/h2\>/g).length === 2 );
- text: Your second `h2` element should be right above the second `section` element's closing tag. It is not in the correct position.
testString: |
const secondSection = document.querySelectorAll('section')[1];
assert( secondSection.lastElementChild.nodeName === 'H2' );
- text: The second `h2` element should have the text `Cat Lists`. You have either omitted the text or have a typo.
testString: assert( document.querySelectorAll('main > section')[1].lastElementChild.innerText.toLowerCase() === 'cat lists');
Your `section` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(
document.querySelectorAll('section').length === 2 &&
code.match(/<\/section>/g).length === 2
);
```
</section>
Your `h2` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
## Challenge Seed
<section id='challengeSeed'>
```js
assert(document.querySelectorAll('h2').length === 2);
```
<div id='html-seed'>
Your `h2` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/h2\>/g).length === 2);
```
Your second `h2` element should be right above the second `section` element's closing tag. It is not in the correct position.
```js
const secondSection = document.querySelectorAll('section')[1];
assert(secondSection.lastElementChild.nodeName === 'H2');
```
The second `h2` element should have the text `Cat Lists`. You have either omitted the text or have a typo.
```js
assert(
document
.querySelectorAll('main > section')[1]
.lastElementChild.innerText.toLowerCase() === 'cat lists'
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -53,14 +63,12 @@ tests:
<p>Click here to view more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a>.</p>
<a href="https://freecatphotoapp.com"><img src="https://bit.ly/fcc-relaxing-cat" alt="A cute orange cat lying on its back."></a>
</section>
--fcc-editable-region--
--fcc-editable-region--
<section>
</section>
--fcc-editable-region--
--fcc-editable-region--
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,41 +4,59 @@ title: Part 18
challengeType: 0
---
## Description
<section id='description'>
# --description--
When you add a lower rank heading element to the page, it's implied that you're starting a new subsection.
After the last `h2` element of the second `section` element, add an `h3` element with the text `Things cats love:`.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: The second `section` element appears to be missing or does not have both an opening and closing tag.
testString: assert( (document.querySelectorAll('main > section')[1] && code.match(/\<\/section>/g).length == 2) );
- text: There should be an `h3` element right above the second `section` element's closing tag.
testString: assert( document.querySelectorAll('main > section')[1].lastElementChild.nodeName === 'H3' );
- text: The `h3` element right above the second `section` element's closing tag should have the text `Things cats love:`. Make sure to include the colon at the end of the text.
testString: assert( document.querySelectorAll('main > section')[1].lastElementChild.innerText.toLowerCase().replace(/\s+/g, ' ') === 'things cats love:' );
- text: There should be an `h2` element with the text `Cat Lists` above the last `h3` element that is nested in the last `section` element'. You may have accidentally deleted the `h2` element.
testString: |
const secondSectionLastElemNode = document.querySelectorAll('main > section')[1].lastElementChild;
assert(
secondSectionLastElemNode.nodeName === 'H3' && secondSectionLastElemNode.previousElementSibling.innerText.toLowerCase().replace(/\s+/g, ' ') === 'cat lists'
);
The second `section` element appears to be missing or does not have both an opening and closing tag.
```js
assert(
document.querySelectorAll('main > section')[1] &&
code.match(/\<\/section>/g).length == 2
);
```
</section>
There should be an `h3` element right above the second `section` element's closing tag.
## Challenge Seed
<section id='challengeSeed'>
```js
assert(
document.querySelectorAll('main > section')[1].lastElementChild.nodeName ===
'H3'
);
```
<div id='html-seed'>
The `h3` element right above the second `section` element's closing tag should have the text `Things cats love:`. Make sure to include the colon at the end of the text.
```js
assert(
document
.querySelectorAll('main > section')[1]
.lastElementChild.innerText.toLowerCase()
.replace(/\s+/g, ' ') === 'things cats love:'
);
```
There should be an `h2` element with the text `Cat Lists` above the last `h3` element that is nested in the last `section` element'. You may have accidentally deleted the `h2` element.
```js
const secondSectionLastElemNode = document.querySelectorAll('main > section')[1]
.lastElementChild;
assert(
secondSectionLastElemNode.nodeName === 'H3' &&
secondSectionLastElemNode.previousElementSibling.innerText
.toLowerCase()
.replace(/\s+/g, ' ') === 'cat lists'
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -51,15 +69,13 @@ tests:
<p>Click here to view more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a>.</p>
<a href="https://freecatphotoapp.com"><img src="https://bit.ly/fcc-relaxing-cat" alt="A cute orange cat lying on its back."></a>
</section>
--fcc-editable-region--
--fcc-editable-region--
<section>
<h2>Cat Lists</h2>
</section>
--fcc-editable-region--
--fcc-editable-region--
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,35 +4,34 @@ title: Part 19
challengeType: 0
---
## Description
<section id='description'>
# --description--
After the `h3` element with the `Things cats love:` text, add an unordered list (`ul`) element. Note that nothing will be displayed at this point.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: 'Your `ul` element should have an opening tag. Opening tags have this syntax: `<elementName>`.'
testString: assert( document.querySelector('ul') );
- text: Your `ul` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/ul>/) );
- text: The `ul` element should be above the second `section` element's closing tag.
testString: |
const secondSectionLastElemNode = $('main > section')[1].lastElementChild;
assert( secondSectionLastElemNode.nodeName === 'UL' );
Your `ul` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('ul'));
```
</section>
Your `ul` element should have a closing tag. Closing tags have a `/` just after the `<` character.
## Challenge Seed
<section id='challengeSeed'>
```js
assert(code.match(/<\/ul>/));
```
<div id='html-seed'>
The `ul` element should be above the second `section` element's closing tag.
```js
const secondSectionLastElemNode = $('main > section')[1].lastElementChild;
assert(secondSectionLastElemNode.nodeName === 'UL');
```
# --seed--
## --seed-contents--
```html
<html>
@@ -46,15 +45,13 @@ tests:
<a href="https://freecatphotoapp.com"><img src="https://bit.ly/fcc-relaxing-cat" alt="A cute orange cat lying on its back."></a>
</section>
<section>
--fcc-editable-region--
--fcc-editable-region--
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
--fcc-editable-region--
--fcc-editable-region--
</section>
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,8 +4,7 @@ title: Part 20
challengeType: 0
---
## Description
<section id='description'>
# --description--
Use list item (`li`) elements to create items in a list. Here is an example of list items in an unordered list:
@@ -16,30 +15,40 @@ Use list item (`li`) elements to create items in a list. Here is an example of l
</ul>
```
Nest three list items within the `ul` element to display three things cats love: `cat nip`, `laser pointers` and `lasagna`.
Nest three list items within the `ul` element to display three things cats love: `cat nip`, `laser pointers` and `lasagna`.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: You should have three `li` elements. Each `li` element should have its own opening and closing tag.
testString: assert( $('li').length === 3 && code.match(/<\/li\>/g).length === 3 );
- text: You should have three `li` elements with the text `cat nip`, `laser pointers` and `lasagna` in any order. You have either omitted some text or have a typo.
testString: assert.deepStrictEqual( [ ...document.querySelectorAll('li') ].map(item => item.innerText.toLowerCase()).sort((a, b) => a.localeCompare(b)), ["cat nip", "lasagna", "laser pointers"] );
- text: The three `li` elements should be located between the `ul` element's opening and closing tags.
testString: assert( [ ...document.querySelectorAll('li') ].filter(item => item.parentNode.nodeName === 'UL').length === 3 );
You should have three `li` elements. Each `li` element should have its own opening and closing tag.
```js
assert($('li').length === 3 && code.match(/<\/li\>/g).length === 3);
```
</section>
You should have three `li` elements with the text `cat nip`, `laser pointers` and `lasagna` in any order. You have either omitted some text or have a typo.
## Challenge Seed
<section id='challengeSeed'>
```js
assert.deepStrictEqual(
[...document.querySelectorAll('li')]
.map((item) => item.innerText.toLowerCase())
.sort((a, b) => a.localeCompare(b)),
['cat nip', 'lasagna', 'laser pointers']
);
```
<div id='html-seed'>
The three `li` elements should be located between the `ul` element's opening and closing tags.
```js
assert(
[...document.querySelectorAll('li')].filter(
(item) => item.parentNode.nodeName === 'UL'
).length === 3
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -55,15 +64,13 @@ tests:
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
--fcc-editable-region--
--fcc-editable-region--
<ul>
</ul>
--fcc-editable-region--
--fcc-editable-region--
</section>
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,39 +4,59 @@ title: Part 21
challengeType: 0
---
## Description
<section id='description'>
# --description--
After the unordered list, add a new image with an `src` attribute value set to `https://bit.ly/fcc-lasagna` and an `alt` attribute value set to `A slice of lasagna on a plate.`
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: There should be an `img` element right above the second `section` element's closing tag.
testString: assert( $('section')[1].lastElementChild.nodeName === 'IMG' );
- text: The new image either does not have an `alt` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
testString: assert($('section')[1].lastElementChild.hasAttribute('alt') );
- text: The new image should have an `alt` value of `A slice of lasagna on a plate.` Make sure the `alt` attribute's value is surrounded with quotation marks.
testString: assert( $('section')[1].lastElementChild.getAttribute('alt').replace(/\s+/g, ' ').match(/^A slice of lasagna on a plate\.?$/i) );
- text: The new image does not have an `src` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
testString: assert($('section')[1].lastElementChild.hasAttribute('src') );
- text: The new image should have an `src` value of `https://bit.ly/fcc-lasagna`. Make sure the `src` attribute's value is surrounded with quotation marks.
testString: assert( $('section')[1].lastElementChild.getAttribute('src') === 'https://bit.ly/fcc-lasagna');
- text: Although you have set the new image's `src` to the correct URL, it is recommended to always surround the value of an attribute with quotation marks.
testString: assert( !/\<img\s+.+\s+src\s*=\s*https:\/\/bit\.ly\/fcc-lasagna/.test(code) );
There should be an `img` element right above the second `section` element's closing tag.
```js
assert($('section')[1].lastElementChild.nodeName === 'IMG');
```
</section>
The new image either does not have an `alt` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
## Challenge Seed
<section id='challengeSeed'>
```js
assert($('section')[1].lastElementChild.hasAttribute('alt'));
```
<div id='html-seed'>
The new image should have an `alt` value of `A slice of lasagna on a plate.` Make sure the `alt` attribute's value is surrounded with quotation marks.
```js
assert(
$('section')[1]
.lastElementChild.getAttribute('alt')
.replace(/\s+/g, ' ')
.match(/^A slice of lasagna on a plate\.?$/i)
);
```
The new image does not have an `src` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
```js
assert($('section')[1].lastElementChild.hasAttribute('src'));
```
The new image should have an `src` value of `https://bit.ly/fcc-lasagna`. Make sure the `src` attribute's value is surrounded with quotation marks.
```js
assert(
$('section')[1].lastElementChild.getAttribute('src') ===
'https://bit.ly/fcc-lasagna'
);
```
Although you have set the new image's `src` to the correct URL, it is recommended to always surround the value of an attribute with quotation marks.
```js
assert(!/\<img\s+.+\s+src\s*=\s*https:\/\/bit\.ly\/fcc-lasagna/.test(code));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -52,18 +72,16 @@ tests:
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
--fcc-editable-region--
--fcc-editable-region--
<ul>
<li>cat nip</li>
<li>laser pointers</li>
<li>lasagna</li>
</ul>
--fcc-editable-region--
--fcc-editable-region--
</section>
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,35 +4,45 @@ title: Part 22
challengeType: 0
---
## Description
<section id='description'>
# --description--
The `figure` element represents self-contained content and will allow you to associate an image with a caption.
Nest the image you just added within a `figure` element.
</section>
## Tests
<section id='tests'>
# --hints--
```yml
tests:
- text: "Your `figure` element should have an opening tag. Opening tags have the following syntax: `<elementName>`."
testString: assert( document.querySelector('figure') );
- text: Your `figure` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/figure\>/) );
- text: There should be an `figure` element right above the second `section` element's closing tag.
testString: assert( $('section')[1].lastElementChild.nodeName === 'FIGURE' );
- text: The lasagna `img` element should be nested in the `figure` element.
testString: assert( document.querySelector('figure > img') && document.querySelector('figure > img').getAttribute('src').toLowerCase() === 'https://bit.ly/fcc-lasagna');
Your `figure` element should have an opening tag. Opening tags have the following syntax: `<elementName>`.
```js
assert(document.querySelector('figure'));
```
</section>
Your `figure` element should have a closing tag. Closing tags have a `/` just after the `<` character.
## Challenge Seed
<section id='challengeSeed'>
```js
assert(code.match(/<\/figure\>/));
```
<div id='html-seed'>
There should be an `figure` element right above the second `section` element's closing tag.
```js
assert($('section')[1].lastElementChild.nodeName === 'FIGURE');
```
The lasagna `img` element should be nested in the `figure` element.
```js
assert(
document.querySelector('figure > img') &&
document.querySelector('figure > img').getAttribute('src').toLowerCase() ===
'https://bit.ly/fcc-lasagna'
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -53,9 +63,9 @@ tests:
<li>laser pointers</li>
<li>lasagna</li>
</ul>
--fcc-editable-region--
--fcc-editable-region--
<img src="https://bit.ly/fcc-lasagna" alt="A slice of lasagna on a plate.">
--fcc-editable-region--
--fcc-editable-region--
</section>
</main>
@@ -63,5 +73,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,42 +4,74 @@ title: Part 23
challengeType: 0
---
## Description
<section id='description'>
# --description--
A figure caption (`figcaption`) element is used to add a caption to describe the image contained withing the `figure` element. For example, `<figcaption>A cute cat</figcaption>` adds the caption `A cute cat`.
After the image nested in the `figure` element, add a `figcaption` element with the text `Cats love lasagna.`
</section>
# --hints--
## Tests
<section id='tests'>
The Lasagna `img` element should be nested in the `figure` element.
```yml
tests:
- text: The Lasagna `img` element should be nested in the `figure` element.
testString: assert( document.querySelector('figure > img') && document.querySelector('figure > img').getAttribute('src').toLowerCase() === 'https://bit.ly/fcc-lasagna');
- text: "Your `figcaption` element should have an opening tag. Opening tags have the following syntax: `<elementName>`."
testString: assert( document.querySelector('figcaption') );
- text: Your `figcaption` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/figcaption\>/) );
- text: The `figcaption` element should be nested in the `figure` element.
testString: assert( document.querySelector('figure > figcaption') && document.querySelector('figure > figcaption'));
- text: The lasagna `img` element should be nested in the `figure` element.
testString: assert( document.querySelector('figure > img') && document.querySelector('figure > img').getAttribute('src').toLowerCase() === 'https://bit.ly/fcc-lasagna');
- text: The `figcaption` element nested in the `figure` element should be below the `img` element. You have them in the wrong order.
testString: assert( document.querySelector('figcaption').previousElementSibling.nodeName === 'IMG');
- text: Your `figcaption` element's text should be `Cats love lasagna.` You have either omitted the text or have a typo.
testString: assert( document.querySelector('figcaption').innerText.match(/Cats love lasagna.?$/i) );
```js
assert(
document.querySelector('figure > img') &&
document.querySelector('figure > img').getAttribute('src').toLowerCase() ===
'https://bit.ly/fcc-lasagna'
);
```
</section>
Your `figcaption` element should have an opening tag. Opening tags have the following syntax: `<elementName>`.
## Challenge Seed
<section id='challengeSeed'>
```js
assert(document.querySelector('figcaption'));
```
<div id='html-seed'>
Your `figcaption` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/figcaption\>/));
```
The `figcaption` element should be nested in the `figure` element.
```js
assert(
document.querySelector('figure > figcaption') &&
document.querySelector('figure > figcaption')
);
```
The lasagna `img` element should be nested in the `figure` element.
```js
assert(
document.querySelector('figure > img') &&
document.querySelector('figure > img').getAttribute('src').toLowerCase() ===
'https://bit.ly/fcc-lasagna'
);
```
The `figcaption` element nested in the `figure` element should be below the `img` element. You have them in the wrong order.
```js
assert(
document.querySelector('figcaption').previousElementSibling.nodeName === 'IMG'
);
```
Your `figcaption` element's text should be `Cats love lasagna.` You have either omitted the text or have a typo.
```js
assert(
document.querySelector('figcaption').innerText.match(/Cats love lasagna.?$/i)
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -61,9 +93,9 @@ tests:
<li>lasagna</li>
</ul>
<figure>
--fcc-editable-region--
--fcc-editable-region--
<img src="https://bit.ly/fcc-lasagna" alt="A slice of lasagna on a plate.">
--fcc-editable-region--
--fcc-editable-region--
</figure>
</section>
</main>
@@ -71,5 +103,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,36 +4,52 @@ title: Part 24
challengeType: 0
---
## Description
<section id='description'>
# --description--
Emphasize the word `love` in the `figcaption` element by wrapping it in an emphasis (`em`) element.
</section>
# --hints--
## Tests
<section id='tests'>
Your emphasis (`em`) element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```yml
tests:
- text: 'Your emphasis (`em`) element should have an opening tag. Opening tags have this syntax: `<elementName>`.'
testString: assert( document.querySelector('em') );
- text: Your emphasis (`em`) element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/em\>/) );
- text: You have either deleted the `figcaption` element or it is missing an opening or closing tag.
testString: assert( document.querySelector('figcaption') && code.match(/<\/figcaption\>/) );
- text: Your emphasis (`em`) element should surround the text `love`. You have either omitted the text or have a typo.
testString: assert( document.querySelector('figcaption > em').innerText.toLowerCase() === 'love' );
- text: The `figcaption`'s text should be `Cats love lasagna`. Check for typos and that the necessary spaces are present around the `em` element's opening and closing tags.
testString: assert( document.querySelector('figcaption').innerText.replace(/\s+/gi, ' ').match(/cats love lasagna\.?/i) );
```js
assert(document.querySelector('em'));
```
</section>
Your emphasis (`em`) element should have a closing tag. Closing tags have a `/` just after the `<` character.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(code.match(/<\/em\>/));
```
You have either deleted the `figcaption` element or it is missing an opening or closing tag.
```js
assert(document.querySelector('figcaption') && code.match(/<\/figcaption\>/));
```
Your emphasis (`em`) element should surround the text `love`. You have either omitted the text or have a typo.
```js
assert(
document.querySelector('figcaption > em').innerText.toLowerCase() === 'love'
);
```
The `figcaption`'s text should be `Cats love lasagna`. Check for typos and that the necessary spaces are present around the `em` element's opening and closing tags.
```js
assert(
document
.querySelector('figcaption')
.innerText.replace(/\s+/gi, ' ')
.match(/cats love lasagna\.?/i)
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -56,9 +72,9 @@ tests:
</ul>
<figure>
<img src="https://bit.ly/fcc-lasagna" alt="A slice of lasagna on a plate.">
--fcc-editable-region--
--fcc-editable-region--
<figcaption>Cats love lasagna.</figcaption>
--fcc-editable-region--
--fcc-editable-region--
</figure>
</section>
</main>
@@ -66,5 +82,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,36 +4,46 @@ title: Part 25
challengeType: 0
---
## Description
<section id='description'>
# --description--
After the `figure` element, add another `h3` element with the text `Top 3 things cats hate:`.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: There should be an `h3` element right above the second `section` element's closing tag. Make it has an opening and closing tag.
testString: assert( document.querySelectorAll('main > section')[1].lastElementChild.nodeName === 'H3' && code.match(/<\/h3\>/g).length === 2);
- text: The new `h3` element should have the text `Top 3 things cats hate:`. Make sure to include the colon at the end of the text.
testString: assert( document.querySelectorAll('main > section')[1].lastElementChild.innerText.toLowerCase().replace(/\s+/g, ' ') === 'top 3 things cats hate:' );
- text: There should be a `figure` above the new `h3` element. You may have accidentally deleted the `figure` element.
testString: |
const secondSectionLastElemNode = document.querySelectorAll('main > section')[1].lastElementChild;
assert(
secondSectionLastElemNode.nodeName === 'H3' && secondSectionLastElemNode.previousElementSibling.nodeName === 'FIGURE'
);
There should be an `h3` element right above the second `section` element's closing tag. Make it has an opening and closing tag.
```js
assert(
document.querySelectorAll('main > section')[1].lastElementChild.nodeName ===
'H3' && code.match(/<\/h3\>/g).length === 2
);
```
</section>
The new `h3` element should have the text `Top 3 things cats hate:`. Make sure to include the colon at the end of the text.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(
document
.querySelectorAll('main > section')[1]
.lastElementChild.innerText.toLowerCase()
.replace(/\s+/g, ' ') === 'top 3 things cats hate:'
);
```
There should be a `figure` above the new `h3` element. You may have accidentally deleted the `figure` element.
```js
const secondSectionLastElemNode = document.querySelectorAll('main > section')[1]
.lastElementChild;
assert(
secondSectionLastElemNode.nodeName === 'H3' &&
secondSectionLastElemNode.previousElementSibling.nodeName === 'FIGURE'
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -54,17 +64,15 @@ tests:
<li>laser pointers</li>
<li>lasagna</li>
</ul>
--fcc-editable-region--
--fcc-editable-region--
<figure>
<img src="https://bit.ly/fcc-lasagna" alt="A slice of lasagna on a plate.">
<figcaption>Cats <em>love</em> lasagna.</figcaption>
</figure>
--fcc-editable-region--
--fcc-editable-region--
</section>
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,38 +4,57 @@ title: Part 26
challengeType: 0
---
## Description
<section id='description'>
# --description--
The code for an ordered list (`ol`) is similar to an unordered list, but list items in an ordered list are numbered when displayed.
After the final second section' last `h3` element, add an ordered list with these three list items: `flea treatment`, `thunder` and `other cats`.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: 'Your `ol` element should have an opening tag. Opening tags have this syntax: `<elementName>`.'
testString: assert( document.querySelector('ol') );
- text: Your `ol` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/ol>/) );
- text: The `ol` element should be above the second `section` element's closing tag. You have them in the wrong order.
testString: assert( $('main > section')[1].lastElementChild.nodeName === 'OL' );
- text: The three `li` elements should be nested inside the `ol` element.
testString: assert( [ ...document.querySelectorAll('li') ].filter(item => item.parentNode.nodeName === 'OL').length === 3);
- text: You should have three `li` elements with the text `flea treatment`, `thunder` and `other cats` in any order.
testString: assert.deepStrictEqual( [ ...document.querySelectorAll('li') ].filter(item => item.parentNode.nodeName === 'OL').map(item => item.innerText.toLowerCase()).sort((a, b) => a.localeCompare(b)), ["flea treatment", "other cats", "thunder"] );
Your `ol` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('ol'));
```
</section>
Your `ol` element should have a closing tag. Closing tags have a `/` just after the `<` character.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(code.match(/<\/ol>/));
```
The `ol` element should be above the second `section` element's closing tag. You have them in the wrong order.
```js
assert($('main > section')[1].lastElementChild.nodeName === 'OL');
```
The three `li` elements should be nested inside the `ol` element.
```js
assert(
[...document.querySelectorAll('li')].filter(
(item) => item.parentNode.nodeName === 'OL'
).length === 3
);
```
You should have three `li` elements with the text `flea treatment`, `thunder` and `other cats` in any order.
```js
assert.deepStrictEqual(
[...document.querySelectorAll('li')]
.filter((item) => item.parentNode.nodeName === 'OL')
.map((item) => item.innerText.toLowerCase())
.sort((a, b) => a.localeCompare(b)),
['flea treatment', 'other cats', 'thunder']
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -60,9 +79,9 @@ tests:
<img src="https://bit.ly/fcc-lasagna" alt="A slice of lasagna on a plate.">
<figcaption>Cats <em>love</em> lasagna.</figcaption>
</figure>
--fcc-editable-region--
--fcc-editable-region--
<h3>Top 3 things cats hate:</h3>
--fcc-editable-region--
--fcc-editable-region--
</section>
</main>
@@ -70,5 +89,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,32 +4,33 @@ title: Part 27
challengeType: 0
---
## Description
<section id='description'>
# --description--
After the ordered list, add another `figure` element.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: 'Your `figure` element should have an opening tag. Opening tags have this syntax: `<elementName>`.'
testString: assert( document.querySelectorAll('figure').length === 2 );
- text: Your `figure` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/figure>/g).length === 2 );
- text: There should be a `figure` element right above the second `section` element's closing tag.
testString: assert( $('main > section')[1].lastElementChild.nodeName === 'FIGURE' );
Your `figure` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelectorAll('figure').length === 2);
```
</section>
Your `figure` element should have a closing tag. Closing tags have a `/` just after the `<` character.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(code.match(/<\/figure>/g).length === 2);
```
There should be a `figure` element right above the second `section` element's closing tag.
```js
assert($('main > section')[1].lastElementChild.nodeName === 'FIGURE');
```
# --seed--
## --seed-contents--
```html
<html>
@@ -55,18 +56,16 @@ tests:
<figcaption>Cats <em>love</em> lasagna.</figcaption>
</figure>
<h3>Top 3 things cats hate:</h3>
--fcc-editable-region--
--fcc-editable-region--
<ol>
<li>flea treatment</li>
<li>thunder</li>
<li>other cats</li>
</ol>
--fcc-editable-region--
--fcc-editable-region--
</section>
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,40 +4,59 @@ title: Part 28
challengeType: 0
---
## Description
<section id='description'>
# --description--
Inside the `figure` element you just added, nest an `img` element with a `src` attribute set to `https://bit.ly/fcc-cats`.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: 'Your second `figure` element should have an opening tag. Opening tags have this syntax: `<elementName>`.'
testString: assert( document.querySelectorAll('figure').length === 2 );
- text: Your second `figure` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/figure>/g).length === 2 );
- text: There should be a second `figure` element right above the second `section` element's closing tag. You have them in the wrong order.
testString: assert( $('main > section')[1].lastElementChild.nodeName === 'FIGURE' );
- text: You should have a third `img` element nested in the `figure` element.
testString: const catsImg = document.querySelectorAll('figure > img')[1]; assert( catsImg && catsImg.getAttribute('src').toLowerCase() === 'https://bit.ly/fcc-cats');
- text: The third image should have an `src` attribute set to `https://bit.ly/fcc-cats`.
testString: |
const catsImg = document.querySelectorAll('figure > img')[1];
assert( catsImg && catsImg.getAttribute('src').toLowerCase() === 'https://bit.ly/fcc-cats');
- text: Although you have set the new image's `src` to the correct URL, it is recommended to always surround the value of an attribute with quotation marks.
testString: assert( !/\<img\s+.+\s+src\s*=\s*https:\/\/bit\.ly\/fcc-cats/.test(code) );
Your second `figure` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelectorAll('figure').length === 2);
```
</section>
Your second `figure` element should have a closing tag. Closing tags have a `/` just after the `<` character.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(code.match(/<\/figure>/g).length === 2);
```
There should be a second `figure` element right above the second `section` element's closing tag. You have them in the wrong order.
```js
assert($('main > section')[1].lastElementChild.nodeName === 'FIGURE');
```
You should have a third `img` element nested in the `figure` element.
```js
const catsImg = document.querySelectorAll('figure > img')[1];
assert(
catsImg &&
catsImg.getAttribute('src').toLowerCase() === 'https://bit.ly/fcc-cats'
);
```
The third image should have an `src` attribute set to `https://bit.ly/fcc-cats`.
```js
const catsImg = document.querySelectorAll('figure > img')[1];
assert(
catsImg &&
catsImg.getAttribute('src').toLowerCase() === 'https://bit.ly/fcc-cats'
);
```
Although you have set the new image's `src` to the correct URL, it is recommended to always surround the value of an attribute with quotation marks.
```js
assert(!/\<img\s+.+\s+src\s*=\s*https:\/\/bit\.ly\/fcc-cats/.test(code));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -68,15 +87,13 @@ tests:
<li>thunder</li>
<li>other cats</li>
</ol>
--fcc-editable-region--
--fcc-editable-region--
<figure>
</figure>
--fcc-editable-region--
--fcc-editable-region--
</section>
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,36 +4,55 @@ title: Part 29
challengeType: 0
---
## Description
<section id='description'>
# --description--
To improve accessibility of the image you just added, add an `alt` attribute with the text `Five cats looking around a field.`
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: 'Your `figure` element should have an opening tag. Opening tags have this syntax: `<elementName>`.'
testString: assert( document.querySelectorAll('figure').length === 2 );
- text: Your `ol` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/figure>/g).length === 2 );
- text: There should be a `figure` element right above the last `section` element's closing tag.
testString: assert( $('main > section')[1].lastElementChild.nodeName === 'FIGURE' );
- text: The Cats `img` element should be nested in the `figure` element.
testString: const catsImg = document.querySelectorAll('figure > img')[1]; assert( catsImg && catsImg.getAttribute('src').toLowerCase() === 'https://bit.ly/fcc-cats');
- text: The Cats `img` element should have an `alt` attribute with the value `Five cats looking around a field.`
testString: const catsImg = document.querySelectorAll('figure > img')[1]; assert( catsImg.getAttribute('alt').replace(/\s+/g, ' ').match(/^Five cats looking around a field\.?$/i) );
Your `figure` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelectorAll('figure').length === 2);
```
</section>
Your `ol` element should have a closing tag. Closing tags have a `/` just after the `<` character.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(code.match(/<\/figure>/g).length === 2);
```
There should be a `figure` element right above the last `section` element's closing tag.
```js
assert($('main > section')[1].lastElementChild.nodeName === 'FIGURE');
```
The Cats `img` element should be nested in the `figure` element.
```js
const catsImg = document.querySelectorAll('figure > img')[1];
assert(
catsImg &&
catsImg.getAttribute('src').toLowerCase() === 'https://bit.ly/fcc-cats'
);
```
The Cats `img` element should have an `alt` attribute with the value `Five cats looking around a field.`
```js
const catsImg = document.querySelectorAll('figure > img')[1];
assert(
catsImg
.getAttribute('alt')
.replace(/\s+/g, ' ')
.match(/^Five cats looking around a field\.?$/i)
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -65,9 +84,9 @@ tests:
<li>other cats</li>
</ol>
<figure>
--fcc-editable-region--
--fcc-editable-region--
<img src="https://bit.ly/fcc-cats">
--fcc-editable-region--
--fcc-editable-region--
</figure>
</section>
</main>
@@ -75,5 +94,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,44 +4,81 @@ title: Part 30
challengeType: 0
---
## Description
<section id='description'>
# --description--
After the last `img` element, add a `figcaption` element with the text `Cats hate other cats.`
</section>
# --hints--
## Tests
<section id='tests'>
Your `figcaption` element should have an opening tag. Opening tags have the following syntax: `<elementName>`.
```yml
tests:
- text: "Your `figcaption` element should have an opening tag. Opening tags have the following syntax: `<elementName>`."
testString: assert( document.querySelectorAll('figcaption').length === 2 );
- text: Your `figcaption` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/figcaption\>/g).length === 2 );
- text: There should be a `figure` element right above the second `section` element's closing tag.
testString: assert( $('main > section')[1].lastElementChild.nodeName === 'FIGURE' );
- text: The last `img` element should be nested in the `figure` element.
testString: const catsImg = document.querySelectorAll('figure > img')[1]; assert( catsImg && catsImg.getAttribute('src').toLowerCase() === 'https://bit.ly/fcc-cats');
- text: "Your `figure` element should have an opening tag. Opening tags have the following syntax: `<elementName>`."
testString: assert( document.querySelectorAll('figure').length === 2 );
- text: Your `figure` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/figure\>/g).length === 2 );
- text: The `figcaption` element should be nested in the `figure` element.
testString: assert( document.querySelectorAll('figure > figcaption').length === 2);
- text: The `figcaption` element nested in the `figure` element should be below the `img` element. You have the `img` element and the `figcaption` element in the wrong order.
testString: assert( document.querySelectorAll('figcaption')[1].previousElementSibling.nodeName === 'IMG');
- text: The `figcaption` element should have the text `Cats hate other cats.` You have omitted a word or have a typo.
testString: assert( document.querySelectorAll('figcaption')[1].innerText.toLowerCase().match(/Cats hate other cats\.?$/i));
```js
assert(document.querySelectorAll('figcaption').length === 2);
```
</section>
Your `figcaption` element should have a closing tag. Closing tags have a `/` just after the `<` character.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(code.match(/<\/figcaption\>/g).length === 2);
```
There should be a `figure` element right above the second `section` element's closing tag.
```js
assert($('main > section')[1].lastElementChild.nodeName === 'FIGURE');
```
The last `img` element should be nested in the `figure` element.
```js
const catsImg = document.querySelectorAll('figure > img')[1];
assert(
catsImg &&
catsImg.getAttribute('src').toLowerCase() === 'https://bit.ly/fcc-cats'
);
```
Your `figure` element should have an opening tag. Opening tags have the following syntax: `<elementName>`.
```js
assert(document.querySelectorAll('figure').length === 2);
```
Your `figure` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/figure\>/g).length === 2);
```
The `figcaption` element should be nested in the `figure` element.
```js
assert(document.querySelectorAll('figure > figcaption').length === 2);
```
The `figcaption` element nested in the `figure` element should be below the `img` element. You have the `img` element and the `figcaption` element in the wrong order.
```js
assert(
document.querySelectorAll('figcaption')[1].previousElementSibling.nodeName ===
'IMG'
);
```
The `figcaption` element should have the text `Cats hate other cats.` You have omitted a word or have a typo.
```js
assert(
document
.querySelectorAll('figcaption')[1]
.innerText.toLowerCase()
.match(/Cats hate other cats\.?$/i)
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -73,9 +110,9 @@ tests:
<li>other cats</li>
</ol>
<figure>
--fcc-editable-region--
--fcc-editable-region--
<img src="https://bit.ly/fcc-cats" alt="Five cats looking around a field.">
--fcc-editable-region--
--fcc-editable-region--
</figure>
</section>
</main>
@@ -83,5 +120,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,36 +4,53 @@ title: Part 31
challengeType: 0
---
## Description
<section id='description'>
# --description--
The `strong` element is used to indicate that some text is of strong importance or urgent.
In the `figcaption` you just added, indicate that `hate` is of strong importance by wrapping it in a `strong` element.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: 'Your `strong` element should have an opening tag. Opening tags have this syntax: `<elementName>`.'
testString: assert( document.querySelector('strong') );
- text: Your strong element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/strong\>/) );
- text: Your strong element should surround the word `hate` in the text `Cats hate other cats.` You have either omitted the text or have a typo.
testString: assert( document.querySelectorAll('figcaption')[1].querySelector('strong').innerText.toLowerCase() === 'hate' );
- text: The `figcaption`'s text should be `Cats hate other cats.` Check for typos and that the necessary spaces are present around the `strong` element's opening and closing tags.
testString: const secondFigCaption = document.querySelectorAll('figcaption')[1]; assert( secondFigCaption && secondFigCaption.innerText.replace(/\s+/gi, ' ').trim().match(/cats hate other cats\.?/i) );
Your `strong` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('strong'));
```
</section>
Your strong element should have a closing tag. Closing tags have a `/` just after the `<` character.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(code.match(/<\/strong\>/));
```
Your strong element should surround the word `hate` in the text `Cats hate other cats.` You have either omitted the text or have a typo.
```js
assert(
document
.querySelectorAll('figcaption')[1]
.querySelector('strong')
.innerText.toLowerCase() === 'hate'
);
```
The `figcaption`'s text should be `Cats hate other cats.` Check for typos and that the necessary spaces are present around the `strong` element's opening and closing tags.
```js
const secondFigCaption = document.querySelectorAll('figcaption')[1];
assert(
secondFigCaption &&
secondFigCaption.innerText
.replace(/\s+/gi, ' ')
.trim()
.match(/cats hate other cats\.?/i)
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -66,9 +83,9 @@ tests:
</ol>
<figure>
<img src="https://bit.ly/fcc-cats" alt="Five cats looking around a field.">
--fcc-editable-region--
--fcc-editable-region--
<figcaption>Cats hate other cats.</figcaption>
--fcc-editable-region--
--fcc-editable-region--
</figure>
</section>
</main>
@@ -76,5 +93,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,43 +4,55 @@ title: Part 32
challengeType: 0
---
## Description
<section id='description'>
# --description--
It is time to add a new section. Add a third `section` element below the second `section` element.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: "Your `section` element should have an opening tag. Opening tags have this syntax: `<elementName>`."
testString: assert( document.querySelectorAll('section').length >= 3 );
- text: You should only add one opening `section` tag. Please remove any extras.
testString: assert( document.querySelectorAll('section').length === 3 );
- text: Your `section` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/section>/g).length >= 3 );
- text: You should only add one closing `section` tag. Please remove any extras.
testString: assert( code.match(/<\/section>/g).length === 3 );
- text: All of the `section` elements should be between the opening and closing tags of the `main` element.
testString: |
const childrenOfMain = [ ...document.querySelector('main').children ];
const sectionElemsFound = childrenOfMain.filter(child => {
return child.nodeName === 'SECTION';
});
assert( sectionElemsFound.length === 3 );
- text: The last `section` element should have no content. Remove any HTML elements or text within the `section` element.
testString: assert( $('main > section')[2].children.length === 0 );
Your `section` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelectorAll('section').length >= 3);
```
</section>
You should only add one opening `section` tag. Please remove any extras.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(document.querySelectorAll('section').length === 3);
```
Your `section` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/section>/g).length >= 3);
```
You should only add one closing `section` tag. Please remove any extras.
```js
assert(code.match(/<\/section>/g).length === 3);
```
All of the `section` elements should be between the opening and closing tags of the `main` element.
```js
const childrenOfMain = [...document.querySelector('main').children];
const sectionElemsFound = childrenOfMain.filter((child) => {
return child.nodeName === 'SECTION';
});
assert(sectionElemsFound.length === 3);
```
The last `section` element should have no content. Remove any HTML elements or text within the `section` element.
```js
assert($('main > section')[2].children.length === 0);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -53,7 +65,7 @@ tests:
<p>Click here to view more <a target="_blank" href="https://freecatphotoapp.com">cat photos</a>.</p>
<a href="https://freecatphotoapp.com"><img src="https://bit.ly/fcc-relaxing-cat" alt="A cute orange cat lying on its back."></a>
</section>
--fcc-editable-region--
--fcc-editable-region--
<section>
<h2>Cat Lists</h2>
<h3>Things cats love:</h3>
@@ -77,11 +89,9 @@ tests:
<figcaption>Cats <strong>hate</strong> other cats.</figcaption>
</figure>
</section>
--fcc-editable-region--
--fcc-editable-region--
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,48 +4,58 @@ title: Part 33
challengeType: 0
---
## Description
<section id='description'>
# --description--
Inside the third `section` element add an `h2` tag with the text `Cat Form`.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: "Unable to find the third `section` element. You may have accidentally deleted it or the opening tag or closing tag."
testString: |
assert(
document.querySelectorAll('section').length === 3 &&
code.match(/<\/section>/g).length === 3
);
- text: Your `h2` element should have an opening tag and closing tag. You may be missing one or both of the required tags.
testString: |
assert(
document.querySelectorAll('h2').length >= 3 &&
code.match(/<\/h2>/g).length >= 3
);
- text: You should only add one `h2` element. Please remove any extras.
testString: assert( document.querySelectorAll('h2').length === 3 );
- text: The new `h2` element should be located right above the third `section` element's closing tag.
testString: |
const thirdSection = document.querySelectorAll('section')[2];
assert( thirdSection.lastElementChild.nodeName === 'H2' );
- text: Your `h2` element's text should be `Cat Form`.
testString: |
const thirdSection = document.querySelectorAll('section')[2];
assert( thirdSection.querySelector('h2').innerText.toLowerCase().replace(/\s+/g, ' ') === 'cat form' );
Unable to find the third `section` element. You may have accidentally deleted it or the opening tag or closing tag.
```js
assert(
document.querySelectorAll('section').length === 3 &&
code.match(/<\/section>/g).length === 3
);
```
</section>
Your `h2` element should have an opening tag and closing tag. You may be missing one or both of the required tags.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(
document.querySelectorAll('h2').length >= 3 &&
code.match(/<\/h2>/g).length >= 3
);
```
You should only add one `h2` element. Please remove any extras.
```js
assert(document.querySelectorAll('h2').length === 3);
```
The new `h2` element should be located right above the third `section` element's closing tag.
```js
const thirdSection = document.querySelectorAll('section')[2];
assert(thirdSection.lastElementChild.nodeName === 'H2');
```
Your `h2` element's text should be `Cat Form`.
```js
const thirdSection = document.querySelectorAll('section')[2];
assert(
thirdSection
.querySelector('h2')
.innerText.toLowerCase()
.replace(/\s+/g, ' ') === 'cat form'
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -81,14 +91,12 @@ tests:
<figcaption>Cats <strong>hate</strong> other cats.</figcaption>
</figure>
</section>
--fcc-editable-region--
--fcc-editable-region--
<section>
</section>
--fcc-editable-region--
--fcc-editable-region--
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,42 +4,42 @@ title: Part 34
challengeType: 0
---
## Description
<section id='description'>
# --description--
Now you will add a web form to collect information from users.
After the `Cat Form` heading, add a `form` element.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: Your `form` element should have an opening tag and closing tag. You may be missing one or both of the required tags, or have them in the wrong order.
testString: |
assert(
document.querySelector('form') &&
code.match(/<\/form>/g)
);
- text: Your `form` element tags are not in the correct order.
testString: |
const noSpaces = code.replace(/\s/g, '');
assert( noSpaces.indexOf('<form>') < noSpaces.indexOf('</form>') );
- text: The `form` element nested in the last `section` element should be below the `h2` element. You have the `h2` element and the `form` element in the wrong order.
testString: assert( document.querySelector('form').previousElementSibling.nodeName === 'H2');
- text: The `form` element should have no content. Remove any HTML elements or text between the `form` element's tags.
testString: assert( $('form')[0].innerHTML.trim().length === 0 );
Your `form` element should have an opening tag and closing tag. You may be missing one or both of the required tags, or have them in the wrong order.
```js
assert(document.querySelector('form') && code.match(/<\/form>/g));
```
</section>
Your `form` element tags are not in the correct order.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
const noSpaces = code.replace(/\s/g, '');
assert(noSpaces.indexOf('<form>') < noSpaces.indexOf('</form>'));
```
The `form` element nested in the last `section` element should be below the `h2` element. You have the `h2` element and the `form` element in the wrong order.
```js
assert(document.querySelector('form').previousElementSibling.nodeName === 'H2');
```
The `form` element should have no content. Remove any HTML elements or text between the `form` element's tags.
```js
assert($('form')[0].innerHTML.trim().length === 0);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -76,14 +76,12 @@ tests:
</figure>
</section>
<section>
--fcc-editable-region--
--fcc-editable-region--
<h2>Cat Form</h2>
--fcc-editable-region--
--fcc-editable-region--
</section>
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,46 +4,68 @@ title: Part 35
challengeType: 0
---
## Description
<section id='description'>
# --description--
The `action` attribute indicates where form data should be sent. For example, `<form action="/submit-url"></form>` tells the browser that the form data should be sent to the path `/submit-url`.
Add an `action` attribute with the value `https://freecatphotoapp.com/submit-cat-photo` to the `form` element.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: Your `form` element should have an opening tag and closing tag in the correct order. You may be missing one or both of the required tags, or have them in the wrong order.
testString: |
const noSpaces = code.replace(/\s/g, '');
assert(
document.querySelector('form') &&
code.match(/<\/form>/g) &&
noSpaces.indexOf('<form') < noSpaces.indexOf('</form>')
);
- text: Your `form` element nested in the last `section` element should be below the `h2` element. You have the `h2` element and the `form` element in the wrong order.
testString: assert( document.querySelector('form').previousElementSibling.nodeName === 'H2');
- text: Your `form` element should have no content. Remove any HTML elements or text between the `form` element's tags.
testString: assert( $('form')[0].innerHTML.trim().length === 0 );
- text: Your `form` element does not have an `action` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
testString: const form = document.querySelector('form'); assert( form.hasAttribute('action') );
- text: Your `form` element should have an `action` attribute with the value `https://freecatphotoapp.com/submit-cat-photo`.
testString: const form = document.querySelector('form'); assert( form.getAttribute('action').match(/^https:\/\/freecatphotoapp\.com\/submit-cat-photo$/) );
- text: Although you have set the `action` attribute to the correct URL, it is recommended to always surround the value of an attribute with quotation marks.
testString: assert( !/\<form\s+action\s*=\s*https:\/\/freecatphotoapp\.com\/submit-cat-photo/.test(code) );
Your `form` element should have an opening tag and closing tag in the correct order. You may be missing one or both of the required tags, or have them in the wrong order.
```js
const noSpaces = code.replace(/\s/g, '');
assert(
document.querySelector('form') &&
code.match(/<\/form>/g) &&
noSpaces.indexOf('<form') < noSpaces.indexOf('</form>')
);
```
</section>
Your `form` element nested in the last `section` element should be below the `h2` element. You have the `h2` element and the `form` element in the wrong order.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(document.querySelector('form').previousElementSibling.nodeName === 'H2');
```
Your `form` element should have no content. Remove any HTML elements or text between the `form` element's tags.
```js
assert($('form')[0].innerHTML.trim().length === 0);
```
Your `form` element does not have an `action` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
```js
const form = document.querySelector('form');
assert(form.hasAttribute('action'));
```
Your `form` element should have an `action` attribute with the value `https://freecatphotoapp.com/submit-cat-photo`.
```js
const form = document.querySelector('form');
assert(
form
.getAttribute('action')
.match(/^https:\/\/freecatphotoapp\.com\/submit-cat-photo$/)
);
```
Although you have set the `action` attribute to the correct URL, it is recommended to always surround the value of an attribute with quotation marks.
```js
assert(
!/\<form\s+action\s*=\s*https:\/\/freecatphotoapp\.com\/submit-cat-photo/.test(
code
)
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -81,15 +103,13 @@ tests:
</section>
<section>
<h2>Cat Form</h2>
--fcc-editable-region--
--fcc-editable-region--
<form>
</form>
--fcc-editable-region--
--fcc-editable-region--
</section>
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,46 +4,61 @@ title: Part 36
challengeType: 0
---
## Description
<section id='description'>
# --description--
The `input` element is allows you several ways to collect data from a web form. Like anchor (`a`) elements, `input` elements are <dfn>self-closing</dfn> and do not need closing tags.
Nest an `input` element in the `form` element.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: Your `form` element should have an opening tag and closing tag in the correct order. You may be missing one or both of the required tags, or have them in the wrong order.
testString: |
const noSpaces = code.replace(/\s/g, '');
assert(
document.querySelector('form') &&
code.match(/<\/form>/g) &&
noSpaces.indexOf('<form') < noSpaces.indexOf('</form>')
);
- text: Your `form` element's opening tag should only have an `action` attribute. Remove anything else you may have typed in it.
testString: assert( [...document.querySelector('form').attributes].length < 2 );
- text: You should create an input element. Check the syntax.
testString: assert( document.querySelector('input') );
- text: Your `input` element should have an opening tag, but not a closing tag.
testString: assert( document.querySelector('input') && !code.match(/<\/input\>/g) );
- text: Your `input` element should be nested within the `form` element.
testString: assert( document.querySelector('form > input') );
- text: Your `form` should only contain the `input` element. Remove any HTML elements or text between the `form` element's tags.
testString: assert( $('form')[0].children.length === 1 && $('form')[0].innerText.trim().length === 0 );
Your `form` element should have an opening tag and closing tag in the correct order. You may be missing one or both of the required tags, or have them in the wrong order.
```js
const noSpaces = code.replace(/\s/g, '');
assert(
document.querySelector('form') &&
code.match(/<\/form>/g) &&
noSpaces.indexOf('<form') < noSpaces.indexOf('</form>')
);
```
</section>
Your `form` element's opening tag should only have an `action` attribute. Remove anything else you may have typed in it.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert([...document.querySelector('form').attributes].length < 2);
```
You should create an input element. Check the syntax.
```js
assert(document.querySelector('input'));
```
Your `input` element should have an opening tag, but not a closing tag.
```js
assert(document.querySelector('input') && !code.match(/<\/input\>/g));
```
Your `input` element should be nested within the `form` element.
```js
assert(document.querySelector('form > input'));
```
Your `form` should only contain the `input` element. Remove any HTML elements or text between the `form` element's tags.
```js
assert(
$('form')[0].children.length === 1 &&
$('form')[0].innerText.trim().length === 0
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -81,15 +96,13 @@ tests:
</section>
<section>
<h2>Cat Form</h2>
--fcc-editable-region--
--fcc-editable-region--
<form action="https://freecatphotoapp.com/submit-cat-photo">
</form>
--fcc-editable-region--
--fcc-editable-region--
</section>
</main>
</body>
</html>
```
</div>
</section>

View File

@@ -4,38 +4,55 @@ title: Part 37
challengeType: 0
---
## Description
<section id='description'>
# --description--
There are many kinds of inputs you can create using the `type` attribute. You can easily create a password field, reset button, or a control to let users select a file from their computer.
Create a text field to get text input from a user by adding the `type` attribute with the value `text` to the `input` element.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: You have either deleted your `input` element or it has invalid syntax. If you have added an attributes, make sure their values are surrounded by quotation marks.
testString: assert( $('input').length );
- text: Your `form` element should only contain the `input` element. Remove any extra HTML elements or text between the `form` element's tags.
testString: assert( $('form')[0].children.length === 1 && $('form')[0].innerText.trim().length === 0 );
- text: Your `input` element does not have a `type` attribute. with the value `text`. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
testString: assert( $('input')[0].hasAttribute('type') );
- text: Your `input` element should have a `type` attribute with the value `text`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
testString: assert( $('input')[0].getAttribute('type').replace(/\s+/g, ' ').match(/^text$/i) );
- text: Although you have set the `input` element's `type` attribute to the `text`, it is recommended to always surround the value of an attribute with quotation marks.
testString: assert( !/\<input\s+type\s*=\s*text/.test(code) );
You have either deleted your `input` element or it has invalid syntax. If you have added an attributes, make sure their values are surrounded by quotation marks.
```js
assert($('input').length);
```
</section>
Your `form` element should only contain the `input` element. Remove any extra HTML elements or text between the `form` element's tags.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(
$('form')[0].children.length === 1 &&
$('form')[0].innerText.trim().length === 0
);
```
Your `input` element does not have a `type` attribute. with the value `text`. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
```js
assert($('input')[0].hasAttribute('type'));
```
Your `input` element should have a `type` attribute with the value `text`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
```js
assert(
$('input')[0]
.getAttribute('type')
.replace(/\s+/g, ' ')
.match(/^text$/i)
);
```
Although you have set the `input` element's `type` attribute to the `text`, it is recommended to always surround the value of an attribute with quotation marks.
```js
assert(!/\<input\s+type\s*=\s*text/.test(code));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -74,9 +91,9 @@ tests:
<section>
<h2>Cat Form</h2>
<form action="https://freecatphotoapp.com/submit-cat-photo">
--fcc-editable-region--
--fcc-editable-region--
<input>
--fcc-editable-region--
--fcc-editable-region--
</form>
</section>
</main>
@@ -84,5 +101,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,38 +4,54 @@ title: Part 38
challengeType: 0
---
## Description
<section id='description'>
# --description--
In order for a form's data to be accessed by the locaton specified in the `action` attribute, you must give the text field a `name` attribute and assign it a value to represent the data being submitted. For example, you could use the following syntax for an email address text field: `<input type="text" name="email">`.
Add the `name` attribute with the value `catphoto ` to your text field.
Add the `name` attribute with the value `catphoto` to your text field.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: You have either deleted your `input` element or it has invalid syntax. All attributes' values should be surrounded by quotation marks.
testString: assert( $('input').length );
- text: Your `form` should only contain the `input` element. Remove any HTML additional elements or text within the `form` element.
testString: assert( $('form')[0].children.length === 1 && $('form')[0].innerText.trim().length === 0 );
- text: Your `input` element does not have a `name` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
testString: assert( $('input')[0].hasAttribute('name') );
- text: Your `input` element should have a `name` attribute with the value `catphotourl`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
testString: assert( $('input')[0].getAttribute('name').match(/^catphotourl$/i) );
- text: Although you have set the `input` element's `name` attribute to `catphotourl`, it is recommended to always surround the value of an attribute with quotation marks.
testString: assert( !/\<\s*input\s+.*\s*=\s*catphotourl/.test(code) );
You have either deleted your `input` element or it has invalid syntax. All attributes' values should be surrounded by quotation marks.
```js
assert($('input').length);
```
</section>
Your `form` should only contain the `input` element. Remove any HTML additional elements or text within the `form` element.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(
$('form')[0].children.length === 1 &&
$('form')[0].innerText.trim().length === 0
);
```
Your `input` element does not have a `name` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
```js
assert($('input')[0].hasAttribute('name'));
```
Your `input` element should have a `name` attribute with the value `catphotourl`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
```js
assert(
$('input')[0]
.getAttribute('name')
.match(/^catphotourl$/i)
);
```
Although you have set the `input` element's `name` attribute to `catphotourl`, it is recommended to always surround the value of an attribute with quotation marks.
```js
assert(!/\<\s*input\s+.*\s*=\s*catphotourl/.test(code));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -74,9 +90,9 @@ tests:
<section>
<h2>Cat Form</h2>
<form action="https://freecatphotoapp.com/submit-cat-photo">
--fcc-editable-region--
--fcc-editable-region--
<input type="text">
--fcc-editable-region--
--fcc-editable-region--
</form>
</section>
</main>
@@ -84,5 +100,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,38 +4,55 @@ title: Part 39
challengeType: 0
---
## Description
<section id='description'>
# --description--
Placeholder text is used to give people a hint about what kind of information to enter into an input. For example, `<input type="text" placeholder="Email address">`.
Add the placeholder text `cat photo URL` to your `input` element.
Add the placeholder text `cat photo URL` to your `input` element.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: You have either deleted your `input` element or it has invalid syntax. All attributes' values should be surrounded by quotation marks.
testString: assert( $('input').length );
- text: Your `form` should only contain the `input` element. Remove any HTML additional elements or text within the `form` element.
testString: assert( $('form')[0].children.length === 1 && $('form')[0].innerText.trim().length === 0 );
- text: Your `input` element does not have a `placeholder` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
testString: assert( $('input')[0].hasAttribute('placeholder') );
- text: Your `input` element should have a `placeholder` attribute with the value `cat photo URL`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
testString: assert( $('input')[0].getAttribute('placeholder').replace(/\s+/g, ' ').match(/^cat photo URL$/i) );
- text: Although you have set the `input` element's `placeholder` attribute to `cat photo URL`, it is recommended to always surround the value of an attribute with quotation marks.
testString: assert( !/\<\s*input\s+placeholder\s*=\s*cat\s+photo\s+url/i.test(code) );
You have either deleted your `input` element or it has invalid syntax. All attributes' values should be surrounded by quotation marks.
```js
assert($('input').length);
```
</section>
Your `form` should only contain the `input` element. Remove any HTML additional elements or text within the `form` element.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(
$('form')[0].children.length === 1 &&
$('form')[0].innerText.trim().length === 0
);
```
Your `input` element does not have a `placeholder` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
```js
assert($('input')[0].hasAttribute('placeholder'));
```
Your `input` element should have a `placeholder` attribute with the value `cat photo URL`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
```js
assert(
$('input')[0]
.getAttribute('placeholder')
.replace(/\s+/g, ' ')
.match(/^cat photo URL$/i)
);
```
Although you have set the `input` element's `placeholder` attribute to `cat photo URL`, it is recommended to always surround the value of an attribute with quotation marks.
```js
assert(!/\<\s*input\s+placeholder\s*=\s*cat\s+photo\s+url/i.test(code));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -74,9 +91,9 @@ tests:
<section>
<h2>Cat Form</h2>
<form action="https://freecatphotoapp.com/submit-cat-photo">
--fcc-editable-region--
--fcc-editable-region--
<input type="text" name="catphotourl">
--fcc-editable-region--
--fcc-editable-region--
</form>
</section>
</main>
@@ -84,5 +101,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,34 +4,42 @@ title: Part 40
challengeType: 0
---
## Description
<section id='description'>
# --description--
To prevent a user from submitting your form when required information is missing, you need to add the `required` attribute to an `input` element. There's no need to set a value to the `required` attribute. Instead, just add the word `required` to the `input` element, making sure there is space between it and other attributes.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: You have either deleted your `input` element or it has invalid syntax. All attributes' values should be surrounded by quotation marks.
testString: assert( $('input').length );
- text: Your `form` should only contain the `input` element. Remove any HTML additional elements or text within the `form` element.
testString: assert( $('form')[0].children.length === 1 && $('form')[0].innerText.trim().length === 0 );
- text: Your `input` element should have a `required` attribute. Remember, you just add the word `required` inside the `input` element's tag.
testString: assert( $('input')[0].hasAttribute('required') );
- text: A value should not be given to the `required` attribute.
testString: assert( $('input')[0].getAttribute('required') === '' );
You have either deleted your `input` element or it has invalid syntax. All attributes' values should be surrounded by quotation marks.
```js
assert($('input').length);
```
</section>
Your `form` should only contain the `input` element. Remove any HTML additional elements or text within the `form` element.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(
$('form')[0].children.length === 1 &&
$('form')[0].innerText.trim().length === 0
);
```
Your `input` element should have a `required` attribute. Remember, you just add the word `required` inside the `input` element's tag.
```js
assert($('input')[0].hasAttribute('required'));
```
A value should not be given to the `required` attribute.
```js
assert($('input')[0].getAttribute('required') === '');
```
# --seed--
## --seed-contents--
```html
<html>
@@ -70,9 +78,9 @@ tests:
<section>
<h2>Cat Form</h2>
<form action="https://freecatphotoapp.com/submit-cat-photo">
--fcc-editable-region--
--fcc-editable-region--
<input type="text" name="catphotourl" placeholder="cat photo URL">
--fcc-editable-region--
--fcc-editable-region--
</form>
</section>
</main>
@@ -80,5 +88,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,36 +4,44 @@ title: Part 41
challengeType: 0
---
## Description
<section id='description'>
# --description--
Use the `button` element to create a clickable button. For example, `<button>Click Here</button>` creates a button with the text `Click Here`.
Add a `button` element with the text `Submit` below the `input` element. Note the default behavior of clicking a form button with any attributes submits the form to the location specified in the form's `action` attribute.
Add a `button` element with the text `Submit` below the `input` element. Note the default behavior of clicking a form button with any attributes submits the form to the location specified in the form's `action` attribute.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: 'Your `button` element should have an opening tag. Opening tags have this syntax: `<elementName>`.'
testString: assert( document.querySelector('button') );
- text: Your `button` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/button\>/) );
- text: Your `button` element's text should be 'Submit'. You have either omitted the text or have a typo.
testString: assert( document.querySelector('button').innerText.toLowerCase() === 'submit' );
- text: Your `button` element should be below the `input` element. You have them in the wrong order.
testString: const collection = [...document.querySelectorAll('input, button')].map(node => node.nodeName); assert( collection.indexOf('INPUT') < collection.indexOf('BUTTON') );
Your `button` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('button'));
```
</section>
Your `button` element should have a closing tag. Closing tags have a `/` just after the `<` character.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(code.match(/<\/button\>/));
```
Your `button` element's text should be 'Submit'. You have either omitted the text or have a typo.
```js
assert(document.querySelector('button').innerText.toLowerCase() === 'submit');
```
Your `button` element should be below the `input` element. You have them in the wrong order.
```js
const collection = [...document.querySelectorAll('input, button')].map(
(node) => node.nodeName
);
assert(collection.indexOf('INPUT') < collection.indexOf('BUTTON'));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -72,9 +80,9 @@ tests:
<section>
<h2>Cat Form</h2>
<form action="https://freecatphotoapp.com/submit-cat-photo">
--fcc-editable-region--
--fcc-editable-region--
<input type="text" name="catphotourl" placeholder="cat photo URL" required>
--fcc-editable-region--
--fcc-editable-region--
</form>
</section>
</main>
@@ -82,5 +90,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,38 +4,51 @@ title: Part 42
challengeType: 0
---
## Description
<section id='description'>
# --description--
Even through you added your button below the text input, they appear next to each other on the page. That's because both `input` and `button` elements are <dfn>inline elements</dfn>, which don't appear on new lines.
You learned previously that the button submits the form by default, but you can explicitly add the `type` attribute with the value `submit` to it to make it clearer. Go ahead and do this to specify this button should submit the form.
You learned previously that the button submits the form by default, but you can explicitly add the `type` attribute with the value `submit` to it to make it clearer. Go ahead and do this to specify this button should submit the form.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: 'Your `button` element should have an opening tag. Opening tags have this syntax: `<elementName>`.'
testString: assert( document.querySelector('button') );
- text: Your `button` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/button\>/) );
- text: Your `button` element does not have a `type` attribute. Check that there is a space after the opening tag's name.
testString: assert( $('button')[0].hasAttribute('type') );
- text: Your `button` element should have a `type` attribute with the value `submit`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
testString: assert( $('button')[0].getAttribute('type').match(/^submit$/i) );
- text: Although you have set the `button` element's `type` attribute to `submit`, it is recommended to always surround the value of an attribute with quotation marks.
testString: assert( !/\<\s*button\s+type\s*=\s*submit/i.test(code) );
Your `button` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('button'));
```
</section>
Your `button` element should have a closing tag. Closing tags have a `/` just after the `<` character.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(code.match(/<\/button\>/));
```
Your `button` element does not have a `type` attribute. Check that there is a space after the opening tag's name.
```js
assert($('button')[0].hasAttribute('type'));
```
Your `button` element should have a `type` attribute with the value `submit`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
```js
assert(
$('button')[0]
.getAttribute('type')
.match(/^submit$/i)
);
```
Although you have set the `button` element's `type` attribute to `submit`, it is recommended to always surround the value of an attribute with quotation marks.
```js
assert(!/\<\s*button\s+type\s*=\s*submit/i.test(code));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -75,9 +88,9 @@ tests:
<h2>Cat Form</h2>
<form action="https://freecatphotoapp.com/submit-cat-photo">
<input type="text" name="catphotourl" placeholder="cat photo URL" required>
--fcc-editable-region--
--fcc-editable-region--
<button>Submit</button>
--fcc-editable-region--
--fcc-editable-region--
</form>
</section>
</main>
@@ -85,5 +98,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,8 +4,7 @@ title: Part 43
challengeType: 0
---
## Description
<section id='description'>
# --description--
You can use radio buttons for questions where you want only one answer out of multiple options.
@@ -13,47 +12,77 @@ Here is an example of a radio button with the option of `cat`: `<input type="rad
Before the text input, add a radio button with the option `Indoor`.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: You should create an input element for your radio button. Check the syntax.
testString: assert( $('form > input').length >= 2 );
- text: Your `input` element should have an opening tag, but not a closing tag.
testString: assert( $('form > input') && !code.match(/<\/input\>/g) );
- text: You should only have added one input element for your radio button. Remove any extras.
testString: assert( $('form > input').length === 2 );
- text: Your new `input` element should be above the existing `input` with `type` attribute set to `text`. You have them in the wrong order.
testString: |
const existingInputElem = document.querySelector('form > input[type="text"]');
assert(
existingInputElem && existingInputElem.previousElementSibling.nodeName === 'INPUT'
);
- text: Your new `input` element does not have a `type` attribute. Check that there is a space after the opening tag's name.
testString: assert( $('input')[0].hasAttribute('type') );
- text: Your new `input` element should have a `type` attribute with the value `radio`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
testString: assert( $('input')[0].getAttribute('type').match(/^radio$/i) );
- text: Although you have set the new `input` element's `type` attribute to `radio`, it is recommended to always surround the value of an attribute with quotation marks.
testString: assert( !/\<\s*input\s+type\s*=\s*radio/i.test(code) );
- text: The `radio` button's ` Indoor` text should be located after it instead of before it.
testString: |
const radioInputElem = $('input')[0];
assert( !radioInputElem.previousSibling.nodeValue.match(/Indoor/i) );
- text: The text ` Indoor` should be located directly to the right of your `radio` button. Make sure there is a space between the element and the text. You have either omitted the text or have a typo.
testString: |
const radioInputElem = $('input')[0];
assert( radioInputElem.nextSibling.nodeValue.replace(/\s+/g, ' ').match(/ Indoor/i) );
You should create an input element for your radio button. Check the syntax.
```js
assert($('form > input').length >= 2);
```
</section>
Your `input` element should have an opening tag, but not a closing tag.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert($('form > input') && !code.match(/<\/input\>/g));
```
You should only have added one input element for your radio button. Remove any extras.
```js
assert($('form > input').length === 2);
```
Your new `input` element should be above the existing `input` with `type` attribute set to `text`. You have them in the wrong order.
```js
const existingInputElem = document.querySelector('form > input[type="text"]');
assert(
existingInputElem &&
existingInputElem.previousElementSibling.nodeName === 'INPUT'
);
```
Your new `input` element does not have a `type` attribute. Check that there is a space after the opening tag's name.
```js
assert($('input')[0].hasAttribute('type'));
```
Your new `input` element should have a `type` attribute with the value `radio`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
```js
assert(
$('input')[0]
.getAttribute('type')
.match(/^radio$/i)
);
```
Although you have set the new `input` element's `type` attribute to `radio`, it is recommended to always surround the value of an attribute with quotation marks.
```js
assert(!/\<\s*input\s+type\s*=\s*radio/i.test(code));
```
The `radio` button's ` Indoor` text should be located after it instead of before it.
```js
const radioInputElem = $('input')[0];
assert(!radioInputElem.previousSibling.nodeValue.match(/Indoor/i));
```
The text ` Indoor` should be located directly to the right of your `radio` button. Make sure there is a space between the element and the text. You have either omitted the text or have a typo.
```js
const radioInputElem = $('input')[0];
assert(
radioInputElem.nextSibling.nodeValue.replace(/\s+/g, ' ').match(/ Indoor/i)
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -92,9 +121,9 @@ tests:
<section>
<h2>Cat Form</h2>
<form action="https://freecatphotoapp.com/submit-cat-photo">
--fcc-editable-region--
--fcc-editable-region--
<input type="text" name="catphotourl" placeholder="cat photo URL" required>
--fcc-editable-region--
--fcc-editable-region--
<button type="submit">Submit</button>
</form>
</section>
@@ -103,5 +132,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,42 +4,53 @@ title: Part 44
challengeType: 0
---
## Description
<section id='description'>
# --description--
`label` elements are used to help associate the text for an `input` element with the input element itself (especially for assistive technologies like screen readers). For example, `<label><input type="radio"> cat</label>` makes it so clicking the word `cat` also selects the corresponding radio button.
Nest your `radio` button inside a `label` element.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: You should make sure the radio button is still present.
testString: assert( $('input[type="radio"]')[0] );
- text: The text ` Indoor` should be located directly to the right of your `radio` button. Make sure there is a space between the element and the text. You have either omitted the text or have a typo.
testString: |
const radioInputElem = $('input')[0];
assert( radioInputElem.nextSibling.nodeValue.replace(/\s+/g, ' ').match(/ Indoor/i) );
- text: 'Your `label` element should have an opening tag. Opening tags have this syntax: `<elementName>`.'
testString: assert( document.querySelector('label') );
- text: Your `label` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/label\>/) );
- text: Your radio button and its text should all be located between the opening and closing tags of the `label` element.
testString: |
const labelChildNodes = [ ...$('form > label')[0].childNodes ];
assert( labelChildNodes.filter(childNode => childNode.nodeName === "INPUT").length );
You should make sure the radio button is still present.
```js
assert($('input[type="radio"]')[0]);
```
</section>
The text ` Indoor` should be located directly to the right of your `radio` button. Make sure there is a space between the element and the text. You have either omitted the text or have a typo.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
const radioInputElem = $('input')[0];
assert(
radioInputElem.nextSibling.nodeValue.replace(/\s+/g, ' ').match(/ Indoor/i)
);
```
Your `label` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelector('label'));
```
Your `label` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/label\>/));
```
Your radio button and its text should all be located between the opening and closing tags of the `label` element.
```js
const labelChildNodes = [...$('form > label')[0].childNodes];
assert(
labelChildNodes.filter((childNode) => childNode.nodeName === 'INPUT').length
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -78,9 +89,9 @@ tests:
<section>
<h2>Cat Form</h2>
<form action="https://freecatphotoapp.com/submit-cat-photo">
--fcc-editable-region--
--fcc-editable-region--
<input type="radio"> Indoor
--fcc-editable-region--
--fcc-editable-region--
<input type="text" name="catphotourl" placeholder="cat photo URL" required>
<button type="submit">Submit</button>
</form>
@@ -90,5 +101,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,36 +4,38 @@ title: Part 45
challengeType: 0
---
## Description
<section id='description'>
# --description--
The `id` attribute is used to identify specific HTML elements. Each `id` attribute's value must be unique all other `id` values for the entire page.
Add an `id` attribute with the value `indoor` to the radio button. When elements have multiple attributes, the order of the attributes doesn't matter.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: Your radio button should still be located between the opening and closing tags of the `label` element.
testString: |
const labelChildNodes = [ ...$('form > label')[0].childNodes ];
assert( labelChildNodes.filter(childNode => childNode.nodeName === "INPUT").length );
- text: Your radio button should have an `id` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
testString: assert( $('input')[0].hasAttribute('id') );
- text: Your radio element should have an `id` attribute with the value `indoor`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
testString: assert( $('input')[0].id.match(/^indoor$/) );
Your radio button should still be located between the opening and closing tags of the `label` element.
```js
const labelChildNodes = [...$('form > label')[0].childNodes];
assert(
labelChildNodes.filter((childNode) => childNode.nodeName === 'INPUT').length
);
```
</section>
Your radio button should have an `id` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert($('input')[0].hasAttribute('id'));
```
Your radio element should have an `id` attribute with the value `indoor`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
```js
assert($('input')[0].id.match(/^indoor$/));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -72,9 +74,9 @@ tests:
<section>
<h2>Cat Form</h2>
<form action="https://freecatphotoapp.com/submit-cat-photo">
--fcc-editable-region--
--fcc-editable-region--
<label><input type="radio"> Indoor</label>
--fcc-editable-region--
--fcc-editable-region--
<input type="text" name="catphotourl" placeholder="cat photo URL" required>
<button type="submit">Submit</button>
</form>
@@ -84,5 +86,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,40 +4,56 @@ title: Part 46
challengeType: 0
---
## Description
<section id='description'>
# --description--
Nest a another radio button with the option `Outdoor` in a new `label` element. The new radio button should be placed after the first one. Also, set its `id` attribute value to `outdoor`.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: You will need to add a new `label` element in which to nest your new radio button. Make sure it has both an opening and closing tag.
testString: assert( document.querySelectorAll('label').length === 2 && code.match(/<\/label\>/g).length === 2 );
- text: The text ` Outdoor` should be located directly to the right of your new `radio` button. Make sure there is a space between the element and the text. You have either omitted the text or have a typo.
testString: |
const radioButtons = [ ...$('input')];
assert( radioButtons.filter(btn => btn.nextSibling.nodeValue.replace(/\s+/g, ' ').match(/ Outdoor/i)).length );
- text: Your new radio button and associated label should be below the first one. You have them in the wrong order.
testString: |
const collection = [...document.querySelectorAll('input[type="radio"]')].map(node => node.nextSibling.nodeValue.replace(/\s+/g, ''));
assert( collection.indexOf('Indoor') < collection.indexOf('Outdoor') );
- text: Your new radio button should have an `id` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
testString: assert( $('input')[1].hasAttribute('id') );
- text: Your new radio element should have an `id` attribute with the value `outdoor`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
testString: assert( $('input')[1].id.match(/^outdoor$/) );
You will need to add a new `label` element in which to nest your new radio button. Make sure it has both an opening and closing tag.
```js
assert(
document.querySelectorAll('label').length === 2 &&
code.match(/<\/label\>/g).length === 2
);
```
</section>
The text ` Outdoor` should be located directly to the right of your new `radio` button. Make sure there is a space between the element and the text. You have either omitted the text or have a typo.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
const radioButtons = [...$('input')];
assert(
radioButtons.filter((btn) =>
btn.nextSibling.nodeValue.replace(/\s+/g, ' ').match(/ Outdoor/i)
).length
);
```
Your new radio button and associated label should be below the first one. You have them in the wrong order.
```js
const collection = [
...document.querySelectorAll('input[type="radio"]')
].map((node) => node.nextSibling.nodeValue.replace(/\s+/g, ''));
assert(collection.indexOf('Indoor') < collection.indexOf('Outdoor'));
```
Your new radio button should have an `id` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
```js
assert($('input')[1].hasAttribute('id'));
```
Your new radio element should have an `id` attribute with the value `outdoor`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
```js
assert($('input')[1].id.match(/^outdoor$/));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -76,9 +92,9 @@ tests:
<section>
<h2>Cat Form</h2>
<form action="https://freecatphotoapp.com/submit-cat-photo">
--fcc-editable-region--
--fcc-editable-region--
<label><input id="indoor" type="radio"> Indoor</label>
--fcc-editable-region--
--fcc-editable-region--
<input type="text" name="catphotourl" placeholder="cat photo URL" required>
<button type="submit">Submit</button>
</form>
@@ -88,5 +104,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,40 +4,47 @@ title: Part 47
challengeType: 0
---
## Description
<section id='description'>
# --description--
Notice that both radio buttons can be selected at the same time. To make it so selecting one radio button automatically deselects the other, both buttons must have a `name` attribute with the same value.
Notice that both radio buttons can be selected at the same time. To make it so selecting one radio button automatically deselects the other, both buttons must have a `name` attribute with the same value.
Add the `name` attribute with the value `indoor-outdoor` to both radio buttons.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: Both radio buttons should still be located between opening and closing `label` element tags.
testString: |
const labelChildNodes = [ ...document.querySelectorAll('form > label') ].map(node => node.childNodes);
assert( labelChildNodes.filter(childNode => childNode[0].nodeName === "INPUT").length === 2 );
- text: Both radio buttons should have a `name` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
testString: |
const radioButtons = [...document.querySelectorAll('input[type="radio"]')];
assert( radioButtons.every(btn => btn.hasAttribute('name')) );
- text: Both radio buttons should have a `name` attribute with the value `indoor-outdoor`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
testString: |
const radioButtons = [ ...$('input[type="radio"]') ];
assert( radioButtons.every(btn => btn.getAttribute('name').match(/^indoor-outdoor$/)) );
Both radio buttons should still be located between opening and closing `label` element tags.
```js
const labelChildNodes = [...document.querySelectorAll('form > label')].map(
(node) => node.childNodes
);
assert(
labelChildNodes.filter((childNode) => childNode[0].nodeName === 'INPUT')
.length === 2
);
```
</section>
Both radio buttons should have a `name` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
const radioButtons = [...document.querySelectorAll('input[type="radio"]')];
assert(radioButtons.every((btn) => btn.hasAttribute('name')));
```
Both radio buttons should have a `name` attribute with the value `indoor-outdoor`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
```js
const radioButtons = [...$('input[type="radio"]')];
assert(
radioButtons.every((btn) =>
btn.getAttribute('name').match(/^indoor-outdoor$/)
)
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -75,10 +82,10 @@ tests:
<section>
<h2>Cat Form</h2>
<form action="https://freecatphotoapp.com/submit-cat-photo">
--fcc-editable-region--
--fcc-editable-region--
<label><input id="indoor" type="radio"> Indoor</label>
<label><input id="outdoor" type="radio"> Outdoor</label>
--fcc-editable-region--
--fcc-editable-region--
<input type="text" name="catphotourl" placeholder="cat photo URL" required>
<button type="submit">Submit</button>
</form>
@@ -88,5 +95,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,44 +4,50 @@ title: Part 48
challengeType: 0
---
## Description
<section id='description'>
# --description--
If you select the `Indoor` radio button and submit the form, the form data for the button is based on its `name` and `value` attributes. Since your radio buttons do not have a `value` attribute, the form data will include `indoor-outdoor=on`, which is not useful when you have multiple buttons.
Add a `value` attribute to both radio buttons. For convenience, set the button's `value` attribute to the same value as its `id` attribute.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: Both radio buttons should still be located between opening and closing `label` element tags.
testString: |
const labelChildNodes = [ ...document.querySelectorAll('form > label') ].map(node => node.childNodes);
assert( labelChildNodes.filter(childNode => childNode[0].nodeName === "INPUT").length === 2 );
- text: Both radio buttons should have a `value` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
testString: |
const radioButtons = [...document.querySelectorAll('input[type="radio"]')];
assert( radioButtons.every(btn => btn.hasAttribute('value')) );
- text: The `Indoor` radio button's `value` attribute should be set to `indoor`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
testString: |
const indoorRadioButton = document.querySelector('#indoor');
assert( indoorRadioButton.getAttribute('value').match(/^indoor$/) );
- text: The `Outdoor` radio button's `value` attribute should be set to `outdoor`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
testString: |
const outdoorRadioButton = document.querySelector('#outdoor');
assert( outdoorRadioButton.getAttribute('value').match(/^outdoor$/) );
Both radio buttons should still be located between opening and closing `label` element tags.
```js
const labelChildNodes = [...document.querySelectorAll('form > label')].map(
(node) => node.childNodes
);
assert(
labelChildNodes.filter((childNode) => childNode[0].nodeName === 'INPUT')
.length === 2
);
```
</section>
Both radio buttons should have a `value` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
const radioButtons = [...document.querySelectorAll('input[type="radio"]')];
assert(radioButtons.every((btn) => btn.hasAttribute('value')));
```
The `Indoor` radio button's `value` attribute should be set to `indoor`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
```js
const indoorRadioButton = document.querySelector('#indoor');
assert(indoorRadioButton.getAttribute('value').match(/^indoor$/));
```
The `Outdoor` radio button's `value` attribute should be set to `outdoor`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
```js
const outdoorRadioButton = document.querySelector('#outdoor');
assert(outdoorRadioButton.getAttribute('value').match(/^outdoor$/));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -79,10 +85,10 @@ tests:
<section>
<h2>Cat Form</h2>
<form action="https://freecatphotoapp.com/submit-cat-photo">
--fcc-editable-region--
--fcc-editable-region--
<label><input id="indoor" type="radio" name="indoor-outdoor"> Indoor</label>
<label><input id="outdoor" type="radio" name="indoor-outdoor"> Outdoor</label>
--fcc-editable-region--
--fcc-editable-region--
<input type="text" name="catphotourl" placeholder="cat photo URL" required>
<button type="submit">Submit</button>
</form>
@@ -92,5 +98,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,40 +4,48 @@ title: Part 49
challengeType: 0
---
## Description
<section id='description'>
# --description--
The `fieldset` element is used to group related inputs and labels together in a web form. `fieldset` elements are <dfn>block-level elements</dfn>, meaning that they appear on a new line.
Nest the `Indoor` and `Outdoor` radio buttons within a `fieldset` element, and don't forget to indent the buttons.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: Both radio buttons should still be located between opening and closing `label` element tags.
testString: |
const labelChildNodes = [ ...$('label') ].map(node => [ ...node.childNodes ]);
assert( labelChildNodes.filter(childNode => childNode[0].nodeName === "INPUT").length === 2 );
- text: "Your `fieldset` element should have an opening tag. Opening tags have the following syntax: `<elementName>`."
testString: assert( document.querySelector('fieldset') );
- text: Your `fieldset` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/fieldset\>/) );
- text: Both radio button and associated labels should be between the opening and closing tags of the `fieldset` element.
testString: |
const radioButtons = [ ...$('input[type="radio"]') ];
assert( radioButtons.every(btn => btn.parentNode.parentNode.nodeName === "FIELDSET") );
Both radio buttons should still be located between opening and closing `label` element tags.
```js
const labelChildNodes = [...$('label')].map((node) => [...node.childNodes]);
assert(
labelChildNodes.filter((childNode) => childNode[0].nodeName === 'INPUT')
.length === 2
);
```
</section>
Your `fieldset` element should have an opening tag. Opening tags have the following syntax: `<elementName>`.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(document.querySelector('fieldset'));
```
Your `fieldset` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/fieldset\>/));
```
Both radio button and associated labels should be between the opening and closing tags of the `fieldset` element.
```js
const radioButtons = [...$('input[type="radio"]')];
assert(
radioButtons.every((btn) => btn.parentNode.parentNode.nodeName === 'FIELDSET')
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -76,10 +84,10 @@ tests:
<section>
<h2>Cat Form</h2>
<form action="https://freecatphotoapp.com/submit-cat-photo">
--fcc-editable-region--
--fcc-editable-region--
<label><input id="indoor" type="radio" name="indoor-outdoor" value="indoor"> Indoor</label>
<label><input id="outdoor" type="radio" name="indoor-outdoor" value="outdoor"> Outdoor</label>
--fcc-editable-region--
--fcc-editable-region--
<input type="text" name="catphotourl" placeholder="cat photo URL" required>
<button type="submit">Submit</button>
</form>
@@ -89,5 +97,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,46 +4,51 @@ title: Part 50
challengeType: 0
---
## Description
<section id='description'>
# --description--
The `legend` element acts as a caption for the content in the `fieldset` element. It gives users context about what they should enter into that part of the form.
Add a `legend` element with the text `Is your cat an indoor or outdoor cat?` above both of the radio buttons.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: "Your `legend` element should have an opening tag. Opening tags have the following syntax: `<elementName>`."
testString: assert( document.querySelector('legend') );
- text: Your `legend` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/legend\>/) );
- text: Your `legend` element should be the first element right below `fieldset` element's opening tag and before the first radio button's opening `label` tag. It is not in the correct position.
testString: |
const fieldsetElem = document.querySelector('fieldset');
const fieldsetElemChildren = fieldsetElem.children;
assert(
fieldsetElem.firstElementChild.nodeName === 'LEGEND' &&
fieldsetElemChildren[1].nodeName === 'LABEL' &&
fieldsetElemChildren[1].children[0].nodeName === 'INPUT' &&
fieldsetElemChildren[1].children[0].id === 'indoor'
);
- text: "Your `legend` element's text should be `Is your cat an indoor or outdoor cat?`. You have either omitted the text, have a typo, or it is not between the `legend` element's opening and closing tags."
testString: |
const extraSpacesRemoved = document.querySelector('legend').innerText.replace(/\s+/g, ' ');
assert( extraSpacesRemoved.match(/Is your cat an indoor or outdoor cat\??$/i) );
Your `legend` element should have an opening tag. Opening tags have the following syntax: `<elementName>`.
```js
assert(document.querySelector('legend'));
```
</section>
Your `legend` element should have a closing tag. Closing tags have a `/` just after the `<` character.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(code.match(/<\/legend\>/));
```
Your `legend` element should be the first element right below `fieldset` element's opening tag and before the first radio button's opening `label` tag. It is not in the correct position.
```js
const fieldsetElem = document.querySelector('fieldset');
const fieldsetElemChildren = fieldsetElem.children;
assert(
fieldsetElem.firstElementChild.nodeName === 'LEGEND' &&
fieldsetElemChildren[1].nodeName === 'LABEL' &&
fieldsetElemChildren[1].children[0].nodeName === 'INPUT' &&
fieldsetElemChildren[1].children[0].id === 'indoor'
);
```
Your `legend` element's text should be `Is your cat an indoor or outdoor cat?`. You have either omitted the text, have a typo, or it is not between the `legend` element's opening and closing tags.
```js
const extraSpacesRemoved = document
.querySelector('legend')
.innerText.replace(/\s+/g, ' ');
assert(extraSpacesRemoved.match(/Is your cat an indoor or outdoor cat\??$/i));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -83,10 +88,10 @@ tests:
<h2>Cat Form</h2>
<form action="https://freecatphotoapp.com/submit-cat-photo">
<fieldset>
--fcc-editable-region--
--fcc-editable-region--
<label><input id="indoor" type="radio" name="indoor-outdoor" value="indoor"> Indoor</label>
<label><input id="outdoor" type="radio" name="indoor-outdoor" value="outdoor"> Outdoor</label>
--fcc-editable-region--
--fcc-editable-region--
</fieldset>
<input type="text" name="catphotourl" placeholder="cat photo URL" required>
<button type="submit">Submit</button>
@@ -97,5 +102,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,55 +4,73 @@ title: Part 51
challengeType: 0
---
## Description
<section id='description'>
# --description--
Next, you are going to add some new form `input` elements, so add another `fieldset` element directly below the current `fieldset` element.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: "Your new `fieldset` element should have an opening tag. Opening tags have this syntax: `<elementName>`."
testString: assert( document.querySelectorAll('fieldset').length >= 2 );
- text: You should only add one opening `fieldset` tag. Please remove any extras.
testString: assert( document.querySelectorAll('fieldset').length === 2 );
- text: Your new `fieldset` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/fieldset>/g).length >= 2 );
- text: You should only add one closing `fieldset` tag. Please remove any extras.
testString: assert( code.match(/<\/fieldset>/g).length === 2 );
- text: The second `fieldset` element should not be nested in the first `fieldset` element.
testString: |
const childrenOf1stFieldset = [ ...document.querySelector('form > fieldset').children ];
const foundElems = childrenOf1stFieldset.filter(child => {
return child.nodeName === 'FIELDSET';
});
assert( foundElems.length === 0 );
- text: Both `fieldset` elements should be above the text field and its associated `label` element. They are out of order.
testString: |
const formChildren = $('form')[0].children;
assert(
formChildren[0].nodeName === 'FIELDSET' &&
formChildren[1].nodeName === 'FIELDSET' &&
formChildren[2] && formChildren[2].nodeName === 'INPUT' &&
formChildren[2].getAttribute('type') === 'text'
);
- text: Your new `fieldset` element should be below the existing `fieldset` element. You have them in the wrong order.
testString: |
const fieldsetChildren = [...document.querySelectorAll('fieldset')].map(elem => elem.children);
assert( fieldsetChildren[0].length > fieldsetChildren
[1].length );
Your new `fieldset` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
```js
assert(document.querySelectorAll('fieldset').length >= 2);
```
</section>
You should only add one opening `fieldset` tag. Please remove any extras.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(document.querySelectorAll('fieldset').length === 2);
```
Your new `fieldset` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/fieldset>/g).length >= 2);
```
You should only add one closing `fieldset` tag. Please remove any extras.
```js
assert(code.match(/<\/fieldset>/g).length === 2);
```
The second `fieldset` element should not be nested in the first `fieldset` element.
```js
const childrenOf1stFieldset = [
...document.querySelector('form > fieldset').children
];
const foundElems = childrenOf1stFieldset.filter((child) => {
return child.nodeName === 'FIELDSET';
});
assert(foundElems.length === 0);
```
Both `fieldset` elements should be above the text field and its associated `label` element. They are out of order.
```js
const formChildren = $('form')[0].children;
assert(
formChildren[0].nodeName === 'FIELDSET' &&
formChildren[1].nodeName === 'FIELDSET' &&
formChildren[2] &&
formChildren[2].nodeName === 'INPUT' &&
formChildren[2].getAttribute('type') === 'text'
);
```
Your new `fieldset` element should be below the existing `fieldset` element. You have them in the wrong order.
```js
const fieldsetChildren = [...document.querySelectorAll('fieldset')].map(
(elem) => elem.children
);
assert(fieldsetChildren[0].length > fieldsetChildren[1].length);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -91,7 +109,7 @@ tests:
<section>
<h2>Cat Form</h2>
<form action="https://freecatphotoapp.com/submit-cat-photo">
--fcc-editable-region--
--fcc-editable-region--
<fieldset>
<legend>Is your cat an indoor or outdoor cat?</legend>
<label><input id="indoor" type="radio" name="indoor-outdoor" value="indoor"> Indoor</label>
@@ -99,7 +117,7 @@ tests:
</fieldset>
<input type="text" name="catphotourl" placeholder="cat photo URL" required>
<button type="submit">Submit</button>
--fcc-editable-region--
--fcc-editable-region--
</form>
</section>
</main>
@@ -107,5 +125,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,46 +4,57 @@ title: Part 52
challengeType: 0
---
## Description
<section id='description'>
# --description--
Add a `legend` element with the text `What's your cat's personality?` inside the second `fieldset` element.
</section>
# --hints--
## Tests
<section id='tests'>
You have either deleted the second `fieldset` element or it is missing an opening tag or closing tag."
```yml
tests:
- text: You have either deleted the second `fieldset` element or it is missing an opening tag or closing tag."
testString: |
assert(
document.querySelectorAll('fieldset').length === 2 &&
code.match(/<\/fieldset>/g).length === 2
);
- text: "Your `legend` element should have an opening tag. Opening tags have this syntax: `<elementName>`."
testString: |
const secondFieldset = $('fieldset')[1];
assert( secondFieldset && [ ...secondFieldset.children ].filter(child => child.nodeName === 'LEGEND').length );
- text: "Your `legend` element should have a closing tag. Closing tags have a `/` just after the `<` character."
testString: assert( code.match(/<\/legend\>/g).length === 2 );
- text: The `legend` element should have the text `What's your cat's personality?`. You have either omitted the text or have a typo.
testString: |
const secondFieldset = $('fieldset')[1];
assert(
secondFieldset && [ ...secondFieldset.children ].filter(child => {
const extraSpacesRemoved = child.innerText.replace(/\s+/g, ' ');
return child.nodeName === 'LEGEND' && extraSpacesRemoved.match(/What's your cat's personality\??$/i) ;
}).length
);
```js
assert(
document.querySelectorAll('fieldset').length === 2 &&
code.match(/<\/fieldset>/g).length === 2
);
```
</section>
Your `legend` element should have an opening tag. Opening tags have this syntax: `<elementName>`.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
const secondFieldset = $('fieldset')[1];
assert(
secondFieldset &&
[...secondFieldset.children].filter((child) => child.nodeName === 'LEGEND')
.length
);
```
Your `legend` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/legend\>/g).length === 2);
```
The `legend` element should have the text `What's your cat's personality?`. You have either omitted the text or have a typo.
```js
const secondFieldset = $('fieldset')[1];
assert(
secondFieldset &&
[...secondFieldset.children].filter((child) => {
const extraSpacesRemoved = child.innerText.replace(/\s+/g, ' ');
return (
child.nodeName === 'LEGEND' &&
extraSpacesRemoved.match(/What's your cat's personality\??$/i)
);
}).length
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -87,10 +98,10 @@ tests:
<label><input id="indoor" type="radio" name="indoor-outdoor" value="indoor"> Indoor</label>
<label><input id="outdoor" type="radio" name="indoor-outdoor" value="outdoor"> Outdoor</label>
</fieldset>
--fcc-editable-region--
--fcc-editable-region--
<fieldset>
</fieldset>
--fcc-editable-region--
--fcc-editable-region--
<input type="text" name="catphotourl" placeholder="cat photo URL" required>
<button type="submit">Submit</button>
</form>
@@ -100,5 +111,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,48 +4,70 @@ title: Part 53
challengeType: 0
---
## Description
<section id='description'>
# --description--
Forms commonly use checkboxes for questions that may have more than one answer. For example, here's a checkbox with the option of `tacos`: `<input type="checkbox"> tacos`.
Under the `legend` element you just added, add an `input` with its `type` attribute set to `checkbox` and give it the option of `Loving`.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: The `input` element for your checkbox should have an opening tag, but not a closing tag.
testString: assert( $('fieldset > input') && !code.match(/<\/input\>/g) );
- text: You should only have added one input element for your checkbox. Remove any extras.
testString: assert( $('fieldset > input').length === 1 );
- text: Your new `input` element should be below the `legend` element with the text `What's your cat's personality?`. You have them in the wrong order.
testString: |
const existingLegendElem = $('fieldset > legend')[1];
assert(
existingLegendElem && existingLegendElem.nextElementSibling.nodeName === 'INPUT'
);
- text: Your new `input` element does not have a `type` attribute. Check that there is a space after the opening tag's name.
testString: assert( $('fieldset > input')[0].hasAttribute('type') );
- text: Your new `input` element should have a `type` attribute with the value `checkbox`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
testString: assert( $('fieldset > input')[0].getAttribute('type').match(/^checkbox$/i) );
- text: Although you have set the new `input` element's `type` attribute to `checkbox`, it is recommended to always surround the value of an attribute with quotation marks.
testString: assert( !/\<\s*input\s+type\s*=\s*checkbox/i.test(code) );
- text: The text ` Loving` should be located directly to the right of your checkbox. Make sure there is a space between the element and the text. You have either omitted the text or have a typo.
testString: |
const checkboxInputElem = $('input[type="checkbox"]')[0];
assert( checkboxInputElem.nextSibling.nodeValue.replace(/\s+/g, ' ').match(/ Loving/i) );
The `input` element for your checkbox should have an opening tag, but not a closing tag.
```js
assert($('fieldset > input') && !code.match(/<\/input\>/g));
```
</section>
You should only have added one input element for your checkbox. Remove any extras.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert($('fieldset > input').length === 1);
```
Your new `input` element should be below the `legend` element with the text `What's your cat's personality?`. You have them in the wrong order.
```js
const existingLegendElem = $('fieldset > legend')[1];
assert(
existingLegendElem &&
existingLegendElem.nextElementSibling.nodeName === 'INPUT'
);
```
Your new `input` element does not have a `type` attribute. Check that there is a space after the opening tag's name.
```js
assert($('fieldset > input')[0].hasAttribute('type'));
```
Your new `input` element should have a `type` attribute with the value `checkbox`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
```js
assert(
$('fieldset > input')[0]
.getAttribute('type')
.match(/^checkbox$/i)
);
```
Although you have set the new `input` element's `type` attribute to `checkbox`, it is recommended to always surround the value of an attribute with quotation marks.
```js
assert(!/\<\s*input\s+type\s*=\s*checkbox/i.test(code));
```
The text ` Loving` should be located directly to the right of your checkbox. Make sure there is a space between the element and the text. You have either omitted the text or have a typo.
```js
const checkboxInputElem = $('input[type="checkbox"]')[0];
assert(
checkboxInputElem.nextSibling.nodeValue.replace(/\s+/g, ' ').match(/ Loving/i)
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -90,9 +112,9 @@ tests:
<label><input id="outdoor" type="radio" name="indoor-outdoor" value="outdoor"> Outdoor</label>
</fieldset>
<fieldset>
--fcc-editable-region--
--fcc-editable-region--
<legend>What's your cat's personality?</legend>
--fcc-editable-region--
--fcc-editable-region--
</fieldset>
<input type="text" name="catphotourl" placeholder="cat photo URL" required>
<button type="submit">Submit</button>
@@ -103,5 +125,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,29 +4,27 @@ title: Part 54
challengeType: 0
---
## Description
<section id='description'>
# --description--
Add an `id` attribute with the value `loving` to the checkbox input.
</section>
## Tests
<section id='tests'>
# --hints--
```yml
tests:
- text: Your checkbox should have an `id` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
testString: assert( $('input[type="checkbox"]')[0].hasAttribute('id') );
- text: Your checkbox should have an `id` attribute with the value `loving`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
testString: assert( $('input[type="checkbox"]')[0].id.match(/^loving$/) );
Your checkbox should have an `id` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
```js
assert($('input[type="checkbox"]')[0].hasAttribute('id'));
```
</section>
Your checkbox should have an `id` attribute with the value `loving`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert($('input[type="checkbox"]')[0].id.match(/^loving$/));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -72,9 +70,9 @@ tests:
</fieldset>
<fieldset>
<legend>What's your cat's personality?</legend>
--fcc-editable-region--
--fcc-editable-region--
<input type="checkbox"> Loving
--fcc-editable-region--
--fcc-editable-region--
</fieldset>
<input type="text" name="catphotourl" placeholder="cat photo URL" required>
<button type="submit">Submit</button>
@@ -85,5 +83,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,54 +4,77 @@ title: Part 55
challengeType: 0
---
## Description
<section id='description'>
# --description--
There's another way to associate an `input` element's text with the element itself. You can nest the text within a `label` element and add a `for` attribute with the same value as the `input` element's `id` attribute.
Associate the text `Loving` with the checkbox by only nesting the text `Loving` in a `label` element and place it to the right side of the checkbox `input` element.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: You should make sure the checkbox is still present.
testString: assert( $('input[type="checkbox"]')[0] );
- text: Your checkbox should still have an `id` attribute with the value `loving`. You may have removed the attribute or changed its value.
testString: assert( $('input[type="checkbox"]')[0].id === 'loving' );
- text: The text ` Loving` should no longer be located directly to the right of your checkbox. It should be wrapped in a `label` element.
testString: |
const checkboxInputElem = $('input[type="checkbox"]')[0];
assert( !checkboxInputElem.nextSibling.nodeValue.replace(/\s+/g, ' ').match(/ Loving/i) );
- text: You will need to add a new `label` element in which to nest the text `Loving`. Make sure it has both an opening and closing tag.
testString: assert( document.querySelectorAll('label').length === 3 && code.match(/<\/label\>/g).length === 3 );
- text: The new `label` element should be located directly to the right of your checkbox. Make sure there is a space between the two elements.
testString: |
const checkboxInputElem = $('input[type="checkbox"]')[0];
assert( checkboxInputElem.nextElementSibling.nodeName === 'LABEL' );
- text: The new `label` element does not have a `for` attribute. Check that there is a space after the opening tag's name.
testString: |
const labelElem = $('input[type="checkbox"]')[0].nextElementSibling;
assert( labelElem.hasAttribute('for') );
- text: The new `label` element should have a `for` attribute with the value `loving`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
testString: |
const labelElem = $('input[type="checkbox"]')[0].nextElementSibling;
assert( labelElem.getAttribute('for').match(/^loving$/) );
- text: The text `Loving` should be nested within the new `label` element. You have either omitted the text or have a typo.
testString: |
const labelElem = document.querySelector('label[for="loving"]');
assert( labelElem.textContent.replace(/\s/g, '').match(/Loving/i) );
You should make sure the checkbox is still present.
```js
assert($('input[type="checkbox"]')[0]);
```
</section>
Your checkbox should still have an `id` attribute with the value `loving`. You may have removed the attribute or changed its value.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert($('input[type="checkbox"]')[0].id === 'loving');
```
The text ` Loving` should no longer be located directly to the right of your checkbox. It should be wrapped in a `label` element.
```js
const checkboxInputElem = $('input[type="checkbox"]')[0];
assert(
!checkboxInputElem.nextSibling.nodeValue
.replace(/\s+/g, ' ')
.match(/ Loving/i)
);
```
You will need to add a new `label` element in which to nest the text `Loving`. Make sure it has both an opening and closing tag.
```js
assert(
document.querySelectorAll('label').length === 3 &&
code.match(/<\/label\>/g).length === 3
);
```
The new `label` element should be located directly to the right of your checkbox. Make sure there is a space between the two elements.
```js
const checkboxInputElem = $('input[type="checkbox"]')[0];
assert(checkboxInputElem.nextElementSibling.nodeName === 'LABEL');
```
The new `label` element does not have a `for` attribute. Check that there is a space after the opening tag's name.
```js
const labelElem = $('input[type="checkbox"]')[0].nextElementSibling;
assert(labelElem.hasAttribute('for'));
```
The new `label` element should have a `for` attribute with the value `loving`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
```js
const labelElem = $('input[type="checkbox"]')[0].nextElementSibling;
assert(labelElem.getAttribute('for').match(/^loving$/));
```
The text `Loving` should be nested within the new `label` element. You have either omitted the text or have a typo.
```js
const labelElem = document.querySelector('label[for="loving"]');
assert(labelElem.textContent.replace(/\s/g, '').match(/Loving/i));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -97,9 +120,9 @@ tests:
</fieldset>
<fieldset>
<legend>What's your cat's personality?</legend>
--fcc-editable-region--
--fcc-editable-region--
<input id="loving" type="checkbox"> Loving
--fcc-editable-region--
--fcc-editable-region--
</fieldset>
<input type="text" name="catphotourl" placeholder="cat photo URL" required>
<button type="submit">Submit</button>
@@ -110,5 +133,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,34 +4,39 @@ title: Part 56
challengeType: 0
---
## Description
<section id='description'>
# --description--
Add the `name` attribute with the value `personality` to the checkbox `input` element.
While you won't notice this in the browser, doing this makes it easier for a server to process your web form, especially when there are multiple checkboxes.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: You should make sure the checkbox is still present.
testString: assert( $('input[type="checkbox"]')[0] );
- text: The checkbox `input` element does not have a `name` attribute. Check that there is a space after the opening tag's name.
testString: assert( $('input[type="checkbox"]')[0].hasAttribute('name') );
- text: The checkbox `input` element should have a `name` attribute with the value `personality`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
testString: assert( $('input[type="checkbox"]')[0].getAttribute('name').match(/^personality$/) );
You should make sure the checkbox is still present.
```js
assert($('input[type="checkbox"]')[0]);
```
</section>
The checkbox `input` element does not have a `name` attribute. Check that there is a space after the opening tag's name.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert($('input[type="checkbox"]')[0].hasAttribute('name'));
```
The checkbox `input` element should have a `name` attribute with the value `personality`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
```js
assert(
$('input[type="checkbox"]')[0]
.getAttribute('name')
.match(/^personality$/)
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -77,9 +82,9 @@ tests:
</fieldset>
<fieldset>
<legend>What's your cat's personality?</legend>
--fcc-editable-region--
--fcc-editable-region--
<input id="loving" type="checkbox"> <label for="loving">Loving</label>
--fcc-editable-region--
--fcc-editable-region--
</fieldset>
<input type="text" name="catphotourl" placeholder="cat photo URL" required>
<button type="submit">Submit</button>
@@ -90,5 +95,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,44 +4,63 @@ title: Part 57
challengeType: 0
---
## Description
<section id='description'>
# --description--
Add another checkbox after the one you just added. The `id` attribute value should be `lazy` and the `name` attribute value should be the same as the last checkbox.
Also add a `label` element to the right of the new checkbox with the text `Lazy`. Make sure to associate the `label` element with the new checkbox using the `for` attribute.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: You need to add a new checkbox.
testString: assert( $('input[type="checkbox"]').length === 2 );
- text: Your new checkbox should have an `id` attribute with the value `lazy` and a `name` attribute with the value `personality`. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
testString: |
const checkboxes = [ ...$('input[type="checkbox"]') ];
assert( checkboxes.some(checkbox => checkbox.id === 'lazy' && checkbox.getAttribute('name') === 'personality') );
- text: Your new checkbox should be after the first one. You have them in the wrong order.
testString: |
const checkboxes = [...$('input[type="checkbox"]')].map(checkbox => checkbox.id);
assert( checkboxes.indexOf('loving') < checkboxes.indexOf('lazy') );
- text: On the right side of your new checkbox, there should be `label` element with the text `Lazy`.
testString: |
const nextElementSibling = $('input[type="checkbox"]')[1].nextElementSibling;
assert( nextElementSibling.nodeName === 'LABEL' && nextElementSibling.innerText.replace(/\s+/g, '').match(/^Lazy$/i) );
- text: The new `label` should have a `for` attribute with the same value as the `id` attribute of the new checkbox. You have either omitted the value or have a typo.
testString: assert( $('input[type="checkbox"]')[1].nextElementSibling.getAttribute('for') === 'lazy' );
You need to add a new checkbox.
```js
assert($('input[type="checkbox"]').length === 2);
```
</section>
Your new checkbox should have an `id` attribute with the value `lazy` and a `name` attribute with the value `personality`. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
const checkboxes = [...$('input[type="checkbox"]')];
assert(
checkboxes.some(
(checkbox) =>
checkbox.id === 'lazy' && checkbox.getAttribute('name') === 'personality'
)
);
```
Your new checkbox should be after the first one. You have them in the wrong order.
```js
const checkboxes = [...$('input[type="checkbox"]')].map(
(checkbox) => checkbox.id
);
assert(checkboxes.indexOf('loving') < checkboxes.indexOf('lazy'));
```
On the right side of your new checkbox, there should be `label` element with the text `Lazy`.
```js
const nextElementSibling = $('input[type="checkbox"]')[1].nextElementSibling;
assert(
nextElementSibling.nodeName === 'LABEL' &&
nextElementSibling.innerText.replace(/\s+/g, '').match(/^Lazy$/i)
);
```
The new `label` should have a `for` attribute with the same value as the `id` attribute of the new checkbox. You have either omitted the value or have a typo.
```js
assert(
$('input[type="checkbox"]')[1].nextElementSibling.getAttribute('for') ===
'lazy'
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -87,9 +106,9 @@ tests:
</fieldset>
<fieldset>
<legend>What's your cat's personality?</legend>
--fcc-editable-region--
--fcc-editable-region--
<input id="loving" type="checkbox" name="personality"> <label for="loving">Loving</label>
--fcc-editable-region--
--fcc-editable-region--
</fieldset>
<input type="text" name="catphotourl" placeholder="cat photo URL" required>
<button type="submit">Submit</button>
@@ -100,5 +119,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,44 +4,64 @@ title: Part 58
challengeType: 0
---
## Description
<section id='description'>
# --description--
Add a final checkbox after the previous one with an `id` attribute value of `energetic`. The `name` and attribute should be the same as the last checkbox.
Also add a `label` element to the right of the new checkbox with text `Energetic`. Make sure to associate the `label` element with the new checkbox.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: You need to add a new checkbox.
testString: assert( $('input[type="checkbox"]').length === 3 );
- text: Your new checkbox should have an `id` attribute with the value `energetic` and a `name` attribute with the value `personality`. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
testString: |
const checkboxes = [ ...$('input[type="checkbox"]') ];
assert( checkboxes.some(checkbox => checkbox.id === 'energetic' && checkbox.getAttribute('name') === 'personality') );
- text: Your new checkbox should be after the first one. You have them in the wrong order.
testString: |
const checkboxes = [...$('input[type="checkbox"]')].map(checkbox => checkbox.id);
assert( checkboxes.indexOf('lazy') < checkboxes.indexOf('energetic') );
- text: On the right side of your new checkbox, there should be `label` element with the text `Energetic`.
testString: |
const nextElementSibling = $('input[type="checkbox"]')[2].nextElementSibling;
assert( nextElementSibling.nodeName === 'LABEL' && nextElementSibling.innerText.replace(/\s+/g, '').match(/^Energetic$/i) );
- text: The new `label` should have a `for` attribute with the same value as the `id` attribute of the new checkbox. You have either omitted the value or have a typo.
testString: assert( $('input[type="checkbox"]')[2].nextElementSibling.getAttribute('for') === 'energetic' );
You need to add a new checkbox.
```js
assert($('input[type="checkbox"]').length === 3);
```
</section>
Your new checkbox should have an `id` attribute with the value `energetic` and a `name` attribute with the value `personality`. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
const checkboxes = [...$('input[type="checkbox"]')];
assert(
checkboxes.some(
(checkbox) =>
checkbox.id === 'energetic' &&
checkbox.getAttribute('name') === 'personality'
)
);
```
Your new checkbox should be after the first one. You have them in the wrong order.
```js
const checkboxes = [...$('input[type="checkbox"]')].map(
(checkbox) => checkbox.id
);
assert(checkboxes.indexOf('lazy') < checkboxes.indexOf('energetic'));
```
On the right side of your new checkbox, there should be `label` element with the text `Energetic`.
```js
const nextElementSibling = $('input[type="checkbox"]')[2].nextElementSibling;
assert(
nextElementSibling.nodeName === 'LABEL' &&
nextElementSibling.innerText.replace(/\s+/g, '').match(/^Energetic$/i)
);
```
The new `label` should have a `for` attribute with the same value as the `id` attribute of the new checkbox. You have either omitted the value or have a typo.
```js
assert(
$('input[type="checkbox"]')[2].nextElementSibling.getAttribute('for') ===
'energetic'
);
```
# --seed--
## --seed-contents--
```html
<html>
@@ -87,10 +107,10 @@ tests:
</fieldset>
<fieldset>
<legend>What's your cat's personality?</legend>
--fcc-editable-region--
--fcc-editable-region--
<input id="loving" type="checkbox" name="personality"> <label for="loving">Loving</label>
<input id="lazy" type="checkbox" name="personality"> <label for="lazy">Lazy</label>
--fcc-editable-region--
--fcc-editable-region--
</fieldset>
<input type="text" name="catphotourl" placeholder="cat photo URL" required>
<button type="submit">Submit</button>
@@ -101,5 +121,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,44 +4,45 @@ title: Part 59
challengeType: 0
---
## Description
<section id='description'>
# --description--
Like radio buttons, form data for selected checkboxes are `name` / `value` attribute pairs. While the `value` attribute is optional, it's best practice to include it with any checkboxes or radio buttons on the page.
Add a `value` attribute to each checkbox. For convenience, set each checkbox's `value` attribute to the same value as its `id` attribute.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: All three checkboxes should have a `value` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
testString: |
const checkboxes = [...document.querySelectorAll('input[type="checkbox"]')];
assert( checkboxes.every(checkbox => checkbox.hasAttribute('value')) );
- text: The `value` attribute of the `Loving` checkbox should be set to `loving`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
testString: |
const lovingCheckbox = document.querySelector('#loving');
assert( lovingCheckbox.getAttribute('value').match(/^loving$/) );
- text: The `value` attribute of the `Lazy` checkbox should be set to `lazy`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
testString: |
const lazyCheckbox = document.querySelector('#lazy');
assert( lazyCheckbox.getAttribute('value').match(/^lazy$/) );
- text: The `value` attribute of the `Energetic` checkbox should be set to `energetic`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
testString: |
const energeticCheckbox = document.querySelector('#energetic');
assert( energeticCheckbox.getAttribute('value').match(/^energetic$/) );
All three checkboxes should have a `value` attribute. Check that there is a space after the opening tag's name and/or there are spaces before all attribute names.
```js
const checkboxes = [...document.querySelectorAll('input[type="checkbox"]')];
assert(checkboxes.every((checkbox) => checkbox.hasAttribute('value')));
```
</section>
The `value` attribute of the `Loving` checkbox should be set to `loving`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
const lovingCheckbox = document.querySelector('#loving');
assert(lovingCheckbox.getAttribute('value').match(/^loving$/));
```
The `value` attribute of the `Lazy` checkbox should be set to `lazy`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
```js
const lazyCheckbox = document.querySelector('#lazy');
assert(lazyCheckbox.getAttribute('value').match(/^lazy$/));
```
The `value` attribute of the `Energetic` checkbox should be set to `energetic`. You have either omitted the value or have a typo. Remember that attribute values should be surrounded with quotation marks.
```js
const energeticCheckbox = document.querySelector('#energetic');
assert(energeticCheckbox.getAttribute('value').match(/^energetic$/));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -80,7 +81,7 @@ tests:
<section>
<h2>Cat Form</h2>
<form action="https://freecatphotoapp.com/submit-cat-photo">
--fcc-editable-region--
--fcc-editable-region--
<fieldset>
<legend>Is your cat an indoor or outdoor cat?</legend>
<label><input id="indoor" type="radio" name="indoor-outdoor" value="indoor"> Indoor</label>
@@ -92,7 +93,7 @@ tests:
<input id="lazy" type="checkbox" name="personality"> <label for="lazy">Lazy</label>
<input id="energetic" type="checkbox" name="personality"> <label for="energetic"> Energetic</label>
</fieldset>
--fcc-editable-region--
--fcc-editable-region--
<input type="text" name="catphotourl" placeholder="cat photo URL" required>
<button type="submit">Submit</button>
</form>
@@ -102,5 +103,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,40 +4,56 @@ title: Part 60
challengeType: 0
---
## Description
<section id='description'>
# --description--
In order to make a checkbox checked or radio button selected by default, you need to add the `checked` attribute to it. There's no need to set a value to the `checked` attribute. Instead, just add the word `checked` to the `input` element, making sure there is space between it and other attributes.
Make the first radio button and the first checkbox selected by default.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: Make sure there still are two radio buttons and three checkboxes nested in their respective `fieldset` elements.
testString: assert( $('input[type="radio"]').length === 2 && $('fieldset > input[type="checkbox"]').length === 3 );
- text: The first radio button is missing the `checked` attribute.
testString: assert( $('input[type="radio"]')[0].hasAttribute('checked') );
- text: The second radio button should not have the `checked` attribute.
testString: assert( !$('input[type="radio"]')[1].hasAttribute('checked') );
- text: The first checkbox is missing the `checked` attribute.
testString: assert( $('input[type="checkbox"]')[0].hasAttribute('checked') );
- text: The second checkbox should not have the `checked` attribute.
testString: assert( !$('input[type="checkbox"]')[1].hasAttribute('checked') );
- text: The third checkbox should not have the `checked` attribute.
testString: assert( !$('input[type="checkbox"]')[2].hasAttribute('checked') );
Make sure there still are two radio buttons and three checkboxes nested in their respective `fieldset` elements.
```js
assert(
$('input[type="radio"]').length === 2 &&
$('fieldset > input[type="checkbox"]').length === 3
);
```
</section>
The first radio button is missing the `checked` attribute.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert($('input[type="radio"]')[0].hasAttribute('checked'));
```
The second radio button should not have the `checked` attribute.
```js
assert(!$('input[type="radio"]')[1].hasAttribute('checked'));
```
The first checkbox is missing the `checked` attribute.
```js
assert($('input[type="checkbox"]')[0].hasAttribute('checked'));
```
The second checkbox should not have the `checked` attribute.
```js
assert(!$('input[type="checkbox"]')[1].hasAttribute('checked'));
```
The third checkbox should not have the `checked` attribute.
```js
assert(!$('input[type="checkbox"]')[2].hasAttribute('checked'));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -76,7 +92,7 @@ tests:
<section>
<h2>Cat Form</h2>
<form action="https://freecatphotoapp.com/submit-cat-photo">
--fcc-editable-region--
--fcc-editable-region--
<fieldset>
<legend>Is your cat an indoor or outdoor cat?</legend>
<label><input id="indoor" type="radio" name="indoor-outdoor" value="indoor"> Indoor</label>
@@ -88,7 +104,7 @@ tests:
<input id="lazy" type="checkbox" name="personality" value="lazy"> <label for="lazy">Lazy</label>
<input id="energetic" type="checkbox" name="personality" value="energetic"> <label for="energetic"> Energetic</label>
</fieldset>
--fcc-editable-region--
--fcc-editable-region--
<input type="text" name="catphotourl" placeholder="cat photo URL" required>
<button type="submit">Submit</button>
</form>
@@ -98,5 +114,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,36 +4,41 @@ title: Part 61
challengeType: 0
---
## Description
<section id='description'>
# --description--
Now you will add a footer section to the page.
Now you will add a footer section to the page.
After the `main` element, add a `footer` element.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: You have either deleted the `main` element or it is missing an opening tag or closing tag."
testString: assert( document.querySelector('main') && code.match(/<\/main>/) );
- text: "Your `footer` element should have an opening tag. Opening tags have the following syntax: `<elementName>`."
testString: assert( document.querySelector('footer') );
- text: Your `footer` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/<\/footer\>/) );
- text: Your `footer` element should the below the closing `main` element tag. You have it put it somewhere else.
testString: assert( document.querySelector('main').nextElementSibling.nodeName === 'FOOTER' );
You have either deleted the `main` element or it is missing an opening tag or closing tag."
```js
assert(document.querySelector('main') && code.match(/<\/main>/));
```
</section>
Your `footer` element should have an opening tag. Opening tags have the following syntax: `<elementName>`.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(document.querySelector('footer'));
```
Your `footer` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/<\/footer\>/));
```
Your `footer` element should the below the closing `main` element tag. You have it put it somewhere else.
```js
assert(document.querySelector('main').nextElementSibling.nodeName === 'FOOTER');
```
# --seed--
## --seed-contents--
```html
<html>
@@ -87,12 +92,10 @@ tests:
<button type="submit">Submit</button>
</form>
</section>
--fcc-editable-region--
--fcc-editable-region--
</main>
</body>
</html>
--fcc-editable-region--
```
</div>
</section>

View File

@@ -4,37 +4,41 @@ title: Part 62
challengeType: 0
---
## Description
<section id='description'>
# --description--
Nest a `p` element with the text `No Copyright - freeCodeCamp.org` within the `footer` element.
</section>
# --hints--
## Tests
<section id='tests'>
You have either deleted the `footer` element or it is missing an opening tag or closing tag."
```yml
tests:
- text: You have either deleted the `footer` element or it is missing an opening tag or closing tag."
testString: assert( document.querySelector('footer') && code.match(/<\/footer>/) );
- text: Your `footer` element should have a `p` element. Make sure to added an opening tag and closing tag for the `p` element.
testString: assert( document.querySelector('footer > p') );
- text: Your `footer` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: |
const pElemClosingTags = code.match(/<\/p\>/g);
assert( pElemClosingTags && pElemClosingTags.length === 2);
- text: "Your `p` element's text should be `No Copyright - freeCodeCamp.org`. You have either omitted the text, have a typo, or it is not between the `legend` element's opening and closing tags."
testString: |
const extraSpacesRemoved = $('footer > p')[0].innerText.replace(/\s+/g, ' ');
assert( extraSpacesRemoved.match(/No Copyright - freeCodeCamp\.org$/i) );
```js
assert(document.querySelector('footer') && code.match(/<\/footer>/));
```
</section>
Your `footer` element should have a `p` element. Make sure to added an opening tag and closing tag for the `p` element.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(document.querySelector('footer > p'));
```
Your `footer` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
const pElemClosingTags = code.match(/<\/p\>/g);
assert(pElemClosingTags && pElemClosingTags.length === 2);
```
Your `p` element's text should be `No Copyright - freeCodeCamp.org`. You have either omitted the text, have a typo, or it is not between the `legend` element's opening and closing tags.
```js
const extraSpacesRemoved = $('footer > p')[0].innerText.replace(/\s+/g, ' ');
assert(extraSpacesRemoved.match(/No Copyright - freeCodeCamp\.org$/i));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -89,13 +93,11 @@ tests:
</form>
</section>
</main>
--fcc-editable-region--
--fcc-editable-region--
<footer>
</footer>
--fcc-editable-region--
--fcc-editable-region--
</body>
</html>
```
</div>
</section>

View File

@@ -4,44 +4,52 @@ title: Part 63
challengeType: 0
---
## Description
<section id='description'>
# --description--
Make the text `freeCodeCamp.org` into a link by enclosing it in an anchor (`a`) element. The `href` attribute should be set to `https://www.freecodecamp.org`.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: Your anchor (`a`) element should be nested within the `footer` element. Make sure to added an opening tag and closing tag for the anchor (`a`) element.
testString: assert( $('footer > p > a').length );
- text: Your anchor (`a`) element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: |
const aElemClosingTags = code.match(/<\/a\>/g);
assert( aElemClosingTags && aElemClosingTags.length === 3);
- text: Your anchor (`a`) element should have an `href` attribute with the value `https://www.freecodecamp.org`. You may have omitted the attribute/value, or have a typo.
testString: |
const nestedAnchor = $('footer > p > a')[0];
assert( nestedAnchor.getAttribute('href') === 'https://www.freecodecamp.org' );
- text: The link's text should be `freeCodeCamp.org`. You have either omitted the text or have a typo.
testString: |
const nestedAnchor = $('footer > p > a')[0];
assert( nestedAnchor.innerText.toLowerCase().replace(/\s+/g, ' ') === 'freecodecamp.org');
- text: After nesting the anchor (`a`) element, the only `p` element content visible in the browser should be `No Copyright - freeCodeCamp.org`. Double check the text, spacing, or punctuation of both the `p` and nested anchor element.
testString: |
const pText = $('footer > p')[0].innerText.toLowerCase().replace(/\s+/g, ' ');
assert( pText.match(/^no copyright - freecodecamp.org$/) );
Your anchor (`a`) element should be nested within the `footer` element. Make sure to added an opening tag and closing tag for the anchor (`a`) element.
```js
assert($('footer > p > a').length);
```
</section>
Your anchor (`a`) element should have a closing tag. Closing tags have a `/` just after the `<` character.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
const aElemClosingTags = code.match(/<\/a\>/g);
assert(aElemClosingTags && aElemClosingTags.length === 3);
```
Your anchor (`a`) element should have an `href` attribute with the value `https://www.freecodecamp.org`. You may have omitted the attribute/value, or have a typo.
```js
const nestedAnchor = $('footer > p > a')[0];
assert(nestedAnchor.getAttribute('href') === 'https://www.freecodecamp.org');
```
The link's text should be `freeCodeCamp.org`. You have either omitted the text or have a typo.
```js
const nestedAnchor = $('footer > p > a')[0];
assert(
nestedAnchor.innerText.toLowerCase().replace(/\s+/g, ' ') ===
'freecodecamp.org'
);
```
After nesting the anchor (`a`) element, the only `p` element content visible in the browser should be `No Copyright - freeCodeCamp.org`. Double check the text, spacing, or punctuation of both the `p` and nested anchor element.
```js
const pText = $('footer > p')[0].innerText.toLowerCase().replace(/\s+/g, ' ');
assert(pText.match(/^no copyright - freecodecamp.org$/));
```
# --seed--
## --seed-contents--
```html
<html>
@@ -98,14 +106,12 @@ tests:
</main>
<footer>
<p>
--fcc-editable-region--
--fcc-editable-region--
No Copyright - freeCodeCamp.org
--fcc-editable-region--
--fcc-editable-region--
</p>
</footer>
</body>
</html>
```
</div>
</section>

View File

@@ -4,42 +4,46 @@ title: Part 64
challengeType: 0
---
## Description
<section id='description'>
# --description--
Notice that everything you've added to the page so far is inside the `body` element. All page content elements that should be rendered to the page go inside the `body` element. However, other important information goes inside the `head` element.
Add a `head` element just above the `body` element.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: You have either deleted the `body` element or it is missing an opening tag or closing tag.
testString: assert( document.querySelector('body') && code.match(/<\/body>/) );
- text: "Your `head` element should have an opening tag. Opening tags have the following syntax: `<elementName>`."
testString: assert( code.match(/\<head\>/) );
- text: Your `head` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: assert( code.match(/\<\/head\>/) );
- text: Your `head` element should be above the opening `body` element tag. You have it put it somewhere else.
testString: |
const noSpaces = code.replace(/\s/g, '');
assert( noSpaces.match(/\<\/head\>\<body\>/) );
You have either deleted the `body` element or it is missing an opening tag or closing tag.
```js
assert(document.querySelector('body') && code.match(/<\/body>/));
```
</section>
Your `head` element should have an opening tag. Opening tags have the following syntax: `<elementName>`.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
assert(code.match(/\<head\>/));
```
Your `head` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/\<\/head\>/));
```
Your `head` element should be above the opening `body` element tag. You have it put it somewhere else.
```js
const noSpaces = code.replace(/\s/g, '');
assert(noSpaces.match(/\<\/head\>\<body\>/));
```
# --seed--
## --seed-contents--
```html
<html>
--fcc-editable-region--
--fcc-editable-region--
<body>
<h1>CatPhotoApp</h1>
<main>
@@ -97,9 +101,7 @@ tests:
</p>
</footer>
</body>
--fcc-editable-region--
--fcc-editable-region--
</html>
```
</div>
</section>

View File

@@ -4,46 +4,49 @@ title: Part 65
challengeType: 0
---
## Description
<section id='description'>
# --description--
The `title` element determines what browsers show in the title bar or tab for the page.
Add a `title` element within the `head` element. Its text should be `CatPhotoApp`.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: You have either deleted the `head` element or it is missing an opening tag or closing tag.
testString: assert( code.match(/\<head\>/) && code.match(/\<\/head\>/) );
- text: Your `title` element should be nested in the `head` element. Make sure to added an opening tag and closing tag for the `title` element.
testString: |
const noSpaces = code.replace(/\s/g, '');
assert( noSpaces.match(/\<head\>\<title\>.*\<\/title\>\<\/head\>/) );
- text: Your `title` element should have a closing tag. Closing tags have a `/` just after the `<` character.
testString: |
assert( code.match(/\<\/title\>/) );
- text: Your `title` element's text should be `CatPhotoApp`. You have either omitted the text or have a typo.
testString: assert( document.title && document.title.toLowerCase() === 'catphotoapp' );
You have either deleted the `head` element or it is missing an opening tag or closing tag.
```js
assert(code.match(/\<head\>/) && code.match(/\<\/head\>/));
```
</section>
Your `title` element should be nested in the `head` element. Make sure to added an opening tag and closing tag for the `title` element.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
const noSpaces = code.replace(/\s/g, '');
assert(noSpaces.match(/\<head\>\<title\>.*\<\/title\>\<\/head\>/));
```
Your `title` element should have a closing tag. Closing tags have a `/` just after the `<` character.
```js
assert(code.match(/\<\/title\>/));
```
Your `title` element's text should be `CatPhotoApp`. You have either omitted the text or have a typo.
```js
assert(document.title && document.title.toLowerCase() === 'catphotoapp');
```
# --seed--
## --seed-contents--
```html
<html>
--fcc-editable-region--
--fcc-editable-region--
<head>
</head>
--fcc-editable-region--
--fcc-editable-region--
<body>
<h1>CatPhotoApp</h1>
<main>
@@ -104,5 +107,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,36 +4,36 @@ title: Part 66
challengeType: 0
---
## Description
<section id='description'>
# --description--
Notice that the entire contents of the page are nested within an `html` element. All other elements must be descendants of this `html` element.
Add the `lang` attribute with the value `en` to the opening `html` tag to specify that the language of the page is English.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: You have either deleted the `html` element or it is missing an opening tag or closing tag.
testString: assert( code.match(/\<html.*?\>/) && code.match(/\<\/html\>/) );
- text: Your `html` element should have a `lang` attribute with the value `en`. You may have omitted the attribute/value, or have a typo.
testString: |
const extraSpacesRemoved = code.replace(/\s+/g, ' ');
assert( extraSpacesRemoved.match(/\<html lang\=("|')([a-z]+)\1\>/) );
- text: Although you have set the `html` element's `lang` attribute to `en`, it is recommended to always surround the value of an attribute with quotation marks.
testString: assert( !/\<\s*html\s+lang\s*=en/i.test(code) );
You have either deleted the `html` element or it is missing an opening tag or closing tag.
```js
assert(code.match(/\<html.*?\>/) && code.match(/\<\/html\>/));
```
</section>
Your `html` element should have a `lang` attribute with the value `en`. You may have omitted the attribute/value, or have a typo.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
const extraSpacesRemoved = code.replace(/\s+/g, ' ');
assert(extraSpacesRemoved.match(/\<html lang\=("|')([a-z]+)\1\>/));
```
Although you have set the `html` element's `lang` attribute to `en`, it is recommended to always surround the value of an attribute with quotation marks.
```js
assert(!/\<\s*html\s+lang\s*=en/i.test(code));
```
# --seed--
## --seed-contents--
```html
--fcc-editable-region--
@@ -102,5 +102,3 @@ tests:
</html>
```
</div>
</section>

View File

@@ -4,34 +4,30 @@ title: Part 67
challengeType: 0
---
## Description
<section id='description'>
# --description--
All pages should begin with `<!DOCTYPE html>`. This special string is known as a <dfn>declaration</dfn> and ensures the browser tries to meet industry-wide specifications.
To complete this project, add this declaration as the first line of the code.
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: Your code should begin with the declaration `<!DOCTYPE html>`. You may have omitted the declaration, have a typo, or it is not the first line of code.
testString: assert( code.match(/\<\s*!DOCTYPE\s+html\s*\>/) );
- text: Your `<!DOCTYPE html>` must be located at the top of the document.
testString: |
const noSpaces = code.replace(/\s/g, '');
assert( noSpaces.match(/^\<\!DOCTYPEhtml\>\<html/) );
Your code should begin with the declaration `<!DOCTYPE html>`. You may have omitted the declaration, have a typo, or it is not the first line of code.
```js
assert(code.match(/\<\s*!DOCTYPE\s+html\s*\>/));
```
</section>
Your `<!DOCTYPE html>` must be located at the top of the document.
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```js
const noSpaces = code.replace(/\s/g, '');
assert(noSpaces.match(/^\<\!DOCTYPEhtml\>\<html/));
```
# --seed--
## --seed-contents--
```html
--fcc-editable-region--
@@ -100,11 +96,7 @@ tests:
</html>
```
</div>
</section>
## Solution
<section id='solution'>
# --solutions--
```html
<!DOCTYPE html>
@@ -171,5 +163,3 @@ tests:
</body>
</html>
```
</section>