mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
chore(curriculum): refactor steps 8 - 13 author project (#57112)
This commit is contained in:
@@ -41,88 +41,68 @@
|
||||
"title": "Step 8"
|
||||
},
|
||||
{
|
||||
"id": "641da5dd6cd6db44f58b7787",
|
||||
"id": "641da73b09e7f046c758e0ed",
|
||||
"title": "Step 9"
|
||||
},
|
||||
{
|
||||
"id": "641da615af82bf454215a992",
|
||||
"id": "641da791d0c34a472b8d15b6",
|
||||
"title": "Step 10"
|
||||
},
|
||||
{
|
||||
"id": "641da6570acf7545931ce477",
|
||||
"id": "641da7bfbc7f0f477438ad8a",
|
||||
"title": "Step 11"
|
||||
},
|
||||
{
|
||||
"id": "641da6dcb6e4c9463d54c75b",
|
||||
"id": "641da803d9892447d059804e",
|
||||
"title": "Step 12"
|
||||
},
|
||||
{
|
||||
"id": "641da7071d0d45467cd59977",
|
||||
"id": "641da836581c254815f785fe",
|
||||
"title": "Step 13"
|
||||
},
|
||||
{
|
||||
"id": "641da73b09e7f046c758e0ed",
|
||||
"id": "641da86294fd9f485d3c2bf0",
|
||||
"title": "Step 14"
|
||||
},
|
||||
{
|
||||
"id": "641da791d0c34a472b8d15b6",
|
||||
"id": "641da895fb7ec648a5bdf19c",
|
||||
"title": "Step 15"
|
||||
},
|
||||
{
|
||||
"id": "641da7bfbc7f0f477438ad8a",
|
||||
"id": "641da8db2a036048ebe6999e",
|
||||
"title": "Step 16"
|
||||
},
|
||||
{
|
||||
"id": "641da803d9892447d059804e",
|
||||
"id": "641da97c987a514959ada414",
|
||||
"title": "Step 17"
|
||||
},
|
||||
{
|
||||
"id": "641da836581c254815f785fe",
|
||||
"id": "641da9aceb788e49a73ebcc9",
|
||||
"title": "Step 18"
|
||||
},
|
||||
{
|
||||
"id": "641da86294fd9f485d3c2bf0",
|
||||
"id": "641da9ea9b847a49fe6ee9b6",
|
||||
"title": "Step 19"
|
||||
},
|
||||
{
|
||||
"id": "641da895fb7ec648a5bdf19c",
|
||||
"id": "641daa5ea050f24a7cade6e6",
|
||||
"title": "Step 20"
|
||||
},
|
||||
{
|
||||
"id": "641da8db2a036048ebe6999e",
|
||||
"title": "Step 21"
|
||||
},
|
||||
{
|
||||
"id": "641da97c987a514959ada414",
|
||||
"title": "Step 22"
|
||||
},
|
||||
{
|
||||
"id": "641da9aceb788e49a73ebcc9",
|
||||
"title": "Step 23"
|
||||
},
|
||||
{
|
||||
"id": "641da9ea9b847a49fe6ee9b6",
|
||||
"title": "Step 24"
|
||||
},
|
||||
{
|
||||
"id": "641daa5ea050f24a7cade6e6",
|
||||
"title": "Step 25"
|
||||
},
|
||||
{
|
||||
"id": "641daa8c2c3e364ac3650b37",
|
||||
"title": "Step 26"
|
||||
"title": "Step 21`"
|
||||
},
|
||||
{
|
||||
"id": "641daabed8d0584b1150c953",
|
||||
"title": "Step 27"
|
||||
"title": "Step 22"
|
||||
},
|
||||
{
|
||||
"id": "641daae5e18eae4b562633e4",
|
||||
"title": "Step 28"
|
||||
"title": "Step 23"
|
||||
},
|
||||
{
|
||||
"id": "641dab13c1b6f14b9828e6b1",
|
||||
"title": "Step 29"
|
||||
"title": "Step 24"
|
||||
}
|
||||
],
|
||||
"helpCategory": "JavaScript"
|
||||
|
||||
+47
-17
@@ -7,40 +7,70 @@ dashedName: step-8
|
||||
|
||||
# --description--
|
||||
|
||||
Now you'll create a function to populate the UI with the author data. You will call this function inside the second `.then()` method.
|
||||
Now, it is time to create the function that will be responsible for displaying the authors on the page.
|
||||
|
||||
Create an empty arrow function named `displayAuthors` that takes `authors` as a parameter.
|
||||
Start by creating a function called `displayAuthors` that takes an `authors` parameter. Your function should then loop through the `authors` array and add a card for each author to the `authorContainer` `div`.
|
||||
|
||||
The card should have the following structure:
|
||||
|
||||
```html
|
||||
<div id="${index}" class="user-card">
|
||||
<h2 class="author-name">${author}</h2>
|
||||
</div>
|
||||
```
|
||||
|
||||
**Tips:**
|
||||
|
||||
- You can use any type of loop to iterate over the `authors` array. Ex. `for`, `forEach`, `map`, etc.
|
||||
- You should use the `innerHTML` property to add the card to the `authorContainer` inside the loop. You will also need to use template literal syntax to add the markup.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should use `const` to create an empty function named `displayAuthors`.
|
||||
|
||||
```js
|
||||
assert.match(code, /const\s+displayAuthors\s*=\s*/)
|
||||
```
|
||||
|
||||
`displayAuthors` should be a function.
|
||||
|
||||
```js
|
||||
assert.isFunction(displayAuthors)
|
||||
```
|
||||
|
||||
Your `displayAuthors` function should use an arrow syntax.
|
||||
|
||||
```js
|
||||
assert.match(code, /const\s+displayAuthors\s*=\s*(\(.*\)|[^\s()]+)\s*=>\s*/)
|
||||
```
|
||||
|
||||
Your `displayAuthors` function should take an `authors` parameter.
|
||||
|
||||
```js
|
||||
assert.match(code, /const\s+displayAuthors\s*=\s*\(?\s*authors/)
|
||||
const parameters = __helpers.getFunctionParams(displayAuthors.toString());
|
||||
assert.deepEqual(parameters[0].name,"authors");
|
||||
```
|
||||
|
||||
Your `displayAuthors` function should be empty.
|
||||
When the `displayAuthors` function is called with an author's array, it should add a card for each author to the `authorContainer` `div`.
|
||||
|
||||
```js
|
||||
assert.match(code, /const\s+displayAuthors\s*=\s*(\(\s*authors\s*\)|authors)\s*=>\s*\{\n?\s*?\}\s*;?/)
|
||||
const exampleAuthors = [
|
||||
[{
|
||||
"author": "Quincy Larson",
|
||||
}, {
|
||||
"author": "Jessica Wilkins",
|
||||
}, ],
|
||||
[{
|
||||
"author": "Naomi Carrigan",
|
||||
}, {
|
||||
"author": "Beau Carnes",
|
||||
}, {
|
||||
"author": "David Clinton",
|
||||
}],
|
||||
];
|
||||
|
||||
for (const authorSet of exampleAuthors) {
|
||||
displayAuthors(authorSet);
|
||||
|
||||
const authorCards = document.querySelectorAll("#author-container div");
|
||||
const authorTitles = document.querySelectorAll("#author-container div h2");
|
||||
assert.deepEqual(authorCards.length, authorTitles.length);
|
||||
for (let i = 0; i < authorCards.length; i++) {
|
||||
assert.deepEqual(authorCards[i].className, "user-card");
|
||||
assert.deepEqual(authorCards[i].id, i.toString());
|
||||
assert.deepEqual(authorTitles[i].className, "author-name");
|
||||
assert.deepEqual(authorTitles[i].innerText, authorSet[i].author);
|
||||
}
|
||||
authorContainer.innerHTML = "";
|
||||
}
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
-144
@@ -1,144 +0,0 @@
|
||||
---
|
||||
id: 641da5dd6cd6db44f58b7787
|
||||
title: Step 9
|
||||
challengeType: 0
|
||||
dashedName: step-9
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Inside your `displayAuthors` function, chain `.forEach()` to `authors`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should chain `.forEach()` to `authors`.
|
||||
|
||||
```js
|
||||
assert.match(code, /authors\.forEach\(\s*\)/)
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>freeCodeCamp News Author Page</title>
|
||||
<link rel="stylesheet" href="./styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="title">freeCodeCamp News Author Page</h1>
|
||||
|
||||
<main>
|
||||
<div id="author-container"></div>
|
||||
<button class="btn" id="load-more-btn">Load More Authors</button>
|
||||
</main>
|
||||
|
||||
<script src="./script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
```css
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:root {
|
||||
--main-bg-color: #1b1b32;
|
||||
--light-grey: #f5f6f7;
|
||||
--dark-purple: #5a01a7;
|
||||
--golden-yellow: #feac32;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--main-bg-color);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: var(--light-grey);
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
#author-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.user-card {
|
||||
border-radius: 15px;
|
||||
width: 300px;
|
||||
height: 350px;
|
||||
background-color: var(--light-grey);
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.user-img {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.purple-divider {
|
||||
background-color: var(--dark-purple);
|
||||
width: 100%;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
.author-name {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.bio {
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.error-msg {
|
||||
color: var(--light-grey);
|
||||
}
|
||||
|
||||
.btn {
|
||||
cursor: pointer;
|
||||
width: 200px;
|
||||
margin: 10px;
|
||||
color: var(--main-bg-color);
|
||||
font-size: 14px;
|
||||
background-color: var(--golden-yellow);
|
||||
background-image: linear-gradient(#fecc4c, #ffac33);
|
||||
border-color: var(--golden-yellow);
|
||||
border-width: 3px;
|
||||
}
|
||||
```
|
||||
|
||||
```js
|
||||
const authorContainer = document.getElementById('author-container');
|
||||
const loadMoreBtn = document.getElementById('load-more-btn');
|
||||
|
||||
let startingIndex = 0;
|
||||
let endingIndex = 8;
|
||||
let authorDataArr = [];
|
||||
|
||||
fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
console.log(data);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(`There was an error: ${err}`);
|
||||
});
|
||||
|
||||
const displayAuthors = (authors) => {
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
};
|
||||
```
|
||||
-164
@@ -1,164 +0,0 @@
|
||||
---
|
||||
id: 641da615af82bf454215a992
|
||||
title: Step 10
|
||||
challengeType: 0
|
||||
dashedName: step-10
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Pass an empty callback function to the `.forEach()` method. For the first parameter of the callback, destructure the `author`, `image`, `url`, and `bio` items.
|
||||
|
||||
For the second parameter, pass in `index`. This will represent the position of each author, and will be useful for pagination later.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should destructure `author`, `image`, `url`, and `bio` as the first parameter of your callback function. Don't forget to put them inside curly braces.
|
||||
|
||||
```js
|
||||
assert.match(code, /authors\.forEach\(\s*\(\s*\{\s*(?:author\s*,\s*image\s*,\s*url\s*,\s*bio)|(?:image\s*,\s*author\s*,\s*url\s*,\s*bio)|(?:url\s*,\s*author\s*,\s*image\s*,\s*bio)|(?:author\s*,\s*url\s*,\s*image\s*,\s*bio)|(?:image\s*,\s*url\s*,\s*author\s*,\s*bio)|(?:url\s*,\s*image\s*,\s*author\s*,\s*bio)|(?:url\s*,\s*image\s*,\s*bio\s*,\s*author)|(?:image\s*,\s*url\s*,\s*bio\s*,\s*author)|(?:bio\s*,\s*url\s*,\s*image\s*,\s*author)|(?:url\s*,\s*bio\s*,\s*image\s*,\s*author)|(?:image\s*,\s*bio\s*,\s*url\s*,\s*author)|(?:bio\s*,\s*image\s*,\s*url\s*,\s*author)|(?:bio\s*,\s*author\s*,\s*url\s*,\s*image)|(?:author\s*,\s*bio\s*,\s*url\s*,\s*image)|(?:url\s*,\s*bio\s*,\s*author\s*,\s*image)|(?:bio\s*,\s*url\s*,\s*author\s*,\s*image)|(?:author\s*,\s*url\s*,\s*bio\s*,\s*image)|(?:url\s*,\s*author\s*,\s*bio\s*,\s*image)|(?:image\s*,\s*author\s*,\s*bio\s*,\s*url)|(?:author\s*,\s*image\s*,\s*bio\s*,\s*url)|(?:bio\s*,\s*image\s*,\s*author\s*,\s*url)|(?:image\s*,\s*bio\s*,\s*author\s*,\s*url)|(?:author\s*,\s*bio\s*,\s*image\s*,\s*url)|(?:bio\s*,\s*author\s*,\s*image\s*,\s*url)\s*\}/)
|
||||
```
|
||||
|
||||
You should destructure `index` as the second parameter of your callback function. It has to be outside of the curly braces you put the others in.
|
||||
|
||||
```js
|
||||
assert.match(code, /authors\.forEach\(\s*\(\s*\{.*\}\s*,\s*index\s*\)/)
|
||||
```
|
||||
|
||||
Your callback function should use an arrow syntax.
|
||||
|
||||
```js
|
||||
assert.match(code, /authors\.forEach\(\s*\(\s*\{.*\}\s*,\s*index\s*\)\s*=>\s*/)
|
||||
```
|
||||
|
||||
Your callback function should be empty.
|
||||
|
||||
```js
|
||||
assert.match(code, /authors\.forEach\(\s*\(\s*\{.*\}\s*,\s*index\s*\)\s*=>\s*\{\s*\}\s*\)\s*;?/)
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>freeCodeCamp News Author Page</title>
|
||||
<link rel="stylesheet" href="./styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="title">freeCodeCamp News Author Page</h1>
|
||||
|
||||
<main>
|
||||
<div id="author-container"></div>
|
||||
<button class="btn" id="load-more-btn">Load More Authors</button>
|
||||
</main>
|
||||
|
||||
<script src="./script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
```css
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:root {
|
||||
--main-bg-color: #1b1b32;
|
||||
--light-grey: #f5f6f7;
|
||||
--dark-purple: #5a01a7;
|
||||
--golden-yellow: #feac32;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--main-bg-color);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: var(--light-grey);
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
#author-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.user-card {
|
||||
border-radius: 15px;
|
||||
width: 300px;
|
||||
height: 350px;
|
||||
background-color: var(--light-grey);
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.user-img {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.purple-divider {
|
||||
background-color: var(--dark-purple);
|
||||
width: 100%;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
.author-name {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.bio {
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.error-msg {
|
||||
color: var(--light-grey);
|
||||
}
|
||||
|
||||
.btn {
|
||||
cursor: pointer;
|
||||
width: 200px;
|
||||
margin: 10px;
|
||||
color: var(--main-bg-color);
|
||||
font-size: 14px;
|
||||
background-color: var(--golden-yellow);
|
||||
background-image: linear-gradient(#fecc4c, #ffac33);
|
||||
border-color: var(--golden-yellow);
|
||||
border-width: 3px;
|
||||
}
|
||||
```
|
||||
|
||||
```js
|
||||
const authorContainer = document.getElementById('author-container');
|
||||
const loadMoreBtn = document.getElementById('load-more-btn');
|
||||
|
||||
let startingIndex = 0;
|
||||
let endingIndex = 8;
|
||||
let authorDataArr = [];
|
||||
|
||||
fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
console.log(data);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(`There was an error: ${err}`);
|
||||
});
|
||||
|
||||
const displayAuthors = (authors) => {
|
||||
--fcc-editable-region--
|
||||
authors.forEach();
|
||||
--fcc-editable-region--
|
||||
};
|
||||
```
|
||||
-155
@@ -1,155 +0,0 @@
|
||||
---
|
||||
id: 641da6570acf7545931ce477
|
||||
title: Step 11
|
||||
challengeType: 0
|
||||
dashedName: step-11
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now it's time to start building the HTML for the page with your destructured data. You can do this with a combination of the compound assignment operator (`+=`) and the `innerHTML` property.
|
||||
|
||||
Inside your callback function, use the compound assignment operator to append an empty template literal to the `innerHTML` of `authorContainer`.
|
||||
|
||||
|
||||
# --hints--
|
||||
|
||||
You should access the `innerHTML` of `authorContainer`.
|
||||
|
||||
```js
|
||||
assert.match(code, /authorContainer\.innerHTML\s*/)
|
||||
```
|
||||
|
||||
You should use compound assignment to append an empty template literal to the `innerHTML` of `authorContainer`.
|
||||
|
||||
```js
|
||||
assert.match(code, /authorContainer\.innerHTML\s*\+=\s*`\s*\n?\s*`\s*;?/)
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>freeCodeCamp News Author Page</title>
|
||||
<link rel="stylesheet" href="./styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="title">freeCodeCamp News Author Page</h1>
|
||||
|
||||
<main>
|
||||
<div id="author-container"></div>
|
||||
<button class="btn" id="load-more-btn">Load More Authors</button>
|
||||
</main>
|
||||
|
||||
<script src="./script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
```css
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:root {
|
||||
--main-bg-color: #1b1b32;
|
||||
--light-grey: #f5f6f7;
|
||||
--dark-purple: #5a01a7;
|
||||
--golden-yellow: #feac32;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--main-bg-color);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: var(--light-grey);
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
#author-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.user-card {
|
||||
border-radius: 15px;
|
||||
width: 300px;
|
||||
height: 350px;
|
||||
background-color: var(--light-grey);
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.user-img {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.purple-divider {
|
||||
background-color: var(--dark-purple);
|
||||
width: 100%;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
.author-name {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.bio {
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.error-msg {
|
||||
color: var(--light-grey);
|
||||
}
|
||||
|
||||
.btn {
|
||||
cursor: pointer;
|
||||
width: 200px;
|
||||
margin: 10px;
|
||||
color: var(--main-bg-color);
|
||||
font-size: 14px;
|
||||
background-color: var(--golden-yellow);
|
||||
background-image: linear-gradient(#fecc4c, #ffac33);
|
||||
border-color: var(--golden-yellow);
|
||||
border-width: 3px;
|
||||
}
|
||||
```
|
||||
|
||||
```js
|
||||
const authorContainer = document.getElementById('author-container');
|
||||
const loadMoreBtn = document.getElementById('load-more-btn');
|
||||
|
||||
let startingIndex = 0;
|
||||
let endingIndex = 8;
|
||||
let authorDataArr = [];
|
||||
|
||||
fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
console.log(data);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(`There was an error: ${err}`);
|
||||
});
|
||||
|
||||
const displayAuthors = (authors) => {
|
||||
authors.forEach(({ author, image, url, bio }, index) => {
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
});
|
||||
};
|
||||
```
|
||||
-162
@@ -1,162 +0,0 @@
|
||||
---
|
||||
id: 641da6dcb6e4c9463d54c75b
|
||||
title: Step 12
|
||||
challengeType: 0
|
||||
dashedName: step-12
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Inside the template literal, create a `div` element with the `id` set to the `index` from the `.forEach()` array method. Remember to use string interpolation to do this.
|
||||
|
||||
Also, add a `class` of `"user-card"` to the `div`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should create a `div` element with the class `"user-card"`.
|
||||
|
||||
```js
|
||||
displayAuthors([{author: "Kolade"}]);
|
||||
assert.include(document.querySelector('#author-container > div')?.className, 'user-card');
|
||||
```
|
||||
|
||||
Your `div` element should have the `id` of `index`. Remember to use string interpolation to set the `id`.
|
||||
|
||||
```js
|
||||
displayAuthors([{author: "Naomi"}]);
|
||||
assert.equal(document.querySelector('#author-container > div')?.id, '0');
|
||||
```
|
||||
|
||||
Your `div` element should be empty.
|
||||
|
||||
```js
|
||||
assert.equal(document.querySelector('#author-container > div')?.innerText, '');
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>freeCodeCamp News Author Page</title>
|
||||
<link rel="stylesheet" href="./styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="title">freeCodeCamp News Author Page</h1>
|
||||
|
||||
<main>
|
||||
<div id="author-container"></div>
|
||||
<button class="btn" id="load-more-btn">Load More Authors</button>
|
||||
</main>
|
||||
|
||||
<script src="./script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
```css
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:root {
|
||||
--main-bg-color: #1b1b32;
|
||||
--light-grey: #f5f6f7;
|
||||
--dark-purple: #5a01a7;
|
||||
--golden-yellow: #feac32;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--main-bg-color);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: var(--light-grey);
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
#author-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.user-card {
|
||||
border-radius: 15px;
|
||||
width: 300px;
|
||||
height: 350px;
|
||||
background-color: var(--light-grey);
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.user-img {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.purple-divider {
|
||||
background-color: var(--dark-purple);
|
||||
width: 100%;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
.author-name {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.bio {
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.error-msg {
|
||||
color: var(--light-grey);
|
||||
}
|
||||
|
||||
.btn {
|
||||
cursor: pointer;
|
||||
width: 200px;
|
||||
margin: 10px;
|
||||
color: var(--main-bg-color);
|
||||
font-size: 14px;
|
||||
background-color: var(--golden-yellow);
|
||||
background-image: linear-gradient(#fecc4c, #ffac33);
|
||||
border-color: var(--golden-yellow);
|
||||
border-width: 3px;
|
||||
}
|
||||
```
|
||||
|
||||
```js
|
||||
const authorContainer = document.getElementById('author-container');
|
||||
const loadMoreBtn = document.getElementById('load-more-btn');
|
||||
|
||||
let startingIndex = 0;
|
||||
let endingIndex = 8;
|
||||
let authorDataArr = [];
|
||||
|
||||
fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
console.log(data);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(`There was an error: ${err}`);
|
||||
});
|
||||
|
||||
const displayAuthors = (authors) => {
|
||||
authors.forEach(({ author, image, url, bio }, index) => {
|
||||
--fcc-editable-region--
|
||||
authorContainer.innerHTML += ``;
|
||||
--fcc-editable-region--
|
||||
});
|
||||
};
|
||||
```
|
||||
-168
@@ -1,168 +0,0 @@
|
||||
---
|
||||
id: 641da7071d0d45467cd59977
|
||||
title: Step 13
|
||||
challengeType: 0
|
||||
dashedName: step-13
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now you need to show some information about the author. First, show the author's name.
|
||||
|
||||
Create an `h2` tag with the `class` `"author-name"`. Then, interpolate `author` inside the `h2` tag. This is the author's name.
|
||||
|
||||
|
||||
# --hints--
|
||||
|
||||
You should create an `h2` element within your `div` element.
|
||||
|
||||
```js
|
||||
displayAuthors([{author: "Kolade"}]);
|
||||
assert.exists(document.querySelector('#author-container > div > h2'));
|
||||
```
|
||||
|
||||
Your `h2` element should have a class set to `"author-name"`
|
||||
|
||||
```js
|
||||
displayAuthors([{name: "Jane", height: 12}])
|
||||
assert.equal(document.querySelector('#author-container > div > h2')?.className, 'author-name');
|
||||
```
|
||||
|
||||
You should interpolate the `author` in your `h2` tag to show the authors' names
|
||||
|
||||
```js
|
||||
displayAuthors([{author: "Kolade"}]);
|
||||
assert.equal(document.querySelector('#author-container > div > h2')?.innerText, 'Kolade');
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>freeCodeCamp News Author Page</title>
|
||||
<link rel="stylesheet" href="./styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="title">freeCodeCamp News Author Page</h1>
|
||||
|
||||
<main>
|
||||
<div id="author-container"></div>
|
||||
<button class="btn" id="load-more-btn">Load More Authors</button>
|
||||
</main>
|
||||
|
||||
<script src="./script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
```css
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:root {
|
||||
--main-bg-color: #1b1b32;
|
||||
--light-grey: #f5f6f7;
|
||||
--dark-purple: #5a01a7;
|
||||
--golden-yellow: #feac32;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--main-bg-color);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: var(--light-grey);
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
#author-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.user-card {
|
||||
border-radius: 15px;
|
||||
width: 300px;
|
||||
height: 350px;
|
||||
background-color: var(--light-grey);
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.user-img {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.purple-divider {
|
||||
background-color: var(--dark-purple);
|
||||
width: 100%;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
.author-name {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.bio {
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.error-msg {
|
||||
color: var(--light-grey);
|
||||
}
|
||||
|
||||
.btn {
|
||||
cursor: pointer;
|
||||
width: 200px;
|
||||
margin: 10px;
|
||||
color: var(--main-bg-color);
|
||||
font-size: 14px;
|
||||
background-color: var(--golden-yellow);
|
||||
background-image: linear-gradient(#fecc4c, #ffac33);
|
||||
border-color: var(--golden-yellow);
|
||||
border-width: 3px;
|
||||
}
|
||||
```
|
||||
|
||||
```js
|
||||
const authorContainer = document.getElementById('author-container');
|
||||
const loadMoreBtn = document.getElementById('load-more-btn');
|
||||
|
||||
let startingIndex = 0;
|
||||
let endingIndex = 8;
|
||||
let authorDataArr = [];
|
||||
|
||||
fetch('https://cdn.freecodecamp.org/curriculum/news-author-page/authors.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
console.log(data);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(`There was an error: ${err}`);
|
||||
});
|
||||
|
||||
const displayAuthors = (authors) => {
|
||||
authors.forEach(({ author, image, url, bio }, index) => {
|
||||
authorContainer.innerHTML += `
|
||||
<div id="${index}" class="user-card">
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
};
|
||||
```
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 641da73b09e7f046c758e0ed
|
||||
title: Step 14
|
||||
title: Step 9
|
||||
challengeType: 0
|
||||
dashedName: step-14
|
||||
dashedName: step-9
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 641da791d0c34a472b8d15b6
|
||||
title: Step 15
|
||||
title: Step 10
|
||||
challengeType: 0
|
||||
dashedName: step-15
|
||||
dashedName: step-10
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 641da7bfbc7f0f477438ad8a
|
||||
title: Step 16
|
||||
title: Step 11
|
||||
challengeType: 0
|
||||
dashedName: step-16
|
||||
dashedName: step-11
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 641da803d9892447d059804e
|
||||
title: Step 17
|
||||
title: Step 12
|
||||
challengeType: 0
|
||||
dashedName: step-17
|
||||
dashedName: step-12
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 641da836581c254815f785fe
|
||||
title: Step 18
|
||||
title: Step 13
|
||||
challengeType: 0
|
||||
dashedName: step-18
|
||||
dashedName: step-13
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 641da86294fd9f485d3c2bf0
|
||||
title: Step 19
|
||||
title: Step 14
|
||||
challengeType: 0
|
||||
dashedName: step-19
|
||||
dashedName: step-14
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 641da895fb7ec648a5bdf19c
|
||||
title: Step 20
|
||||
title: Step 15
|
||||
challengeType: 0
|
||||
dashedName: step-20
|
||||
dashedName: step-15
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 641da8db2a036048ebe6999e
|
||||
title: Step 21
|
||||
title: Step 16
|
||||
challengeType: 0
|
||||
dashedName: step-21
|
||||
dashedName: step-16
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 641da97c987a514959ada414
|
||||
title: Step 22
|
||||
title: Step 17
|
||||
challengeType: 0
|
||||
dashedName: step-22
|
||||
dashedName: step-17
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 641da9aceb788e49a73ebcc9
|
||||
title: Step 23
|
||||
title: Step 18
|
||||
challengeType: 0
|
||||
dashedName: step-23
|
||||
dashedName: step-18
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 641da9ea9b847a49fe6ee9b6
|
||||
title: Step 24
|
||||
title: Step 19
|
||||
challengeType: 0
|
||||
dashedName: step-24
|
||||
dashedName: step-19
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 641daa5ea050f24a7cade6e6
|
||||
title: Step 25
|
||||
title: Step 20
|
||||
challengeType: 0
|
||||
dashedName: step-25
|
||||
dashedName: step-20
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 641daa8c2c3e364ac3650b37
|
||||
title: Step 26
|
||||
title: Step 21
|
||||
challengeType: 0
|
||||
dashedName: step-26
|
||||
dashedName: step-21
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 641daabed8d0584b1150c953
|
||||
title: Step 27
|
||||
title: Step 22
|
||||
challengeType: 0
|
||||
dashedName: step-27
|
||||
dashedName: step-22
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 641daae5e18eae4b562633e4
|
||||
title: Step 28
|
||||
title: Step 23
|
||||
challengeType: 0
|
||||
dashedName: step-28
|
||||
dashedName: step-23
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
---
|
||||
id: 641dab13c1b6f14b9828e6b1
|
||||
title: Step 29
|
||||
title: Step 24
|
||||
challengeType: 0
|
||||
dashedName: step-29
|
||||
dashedName: step-24
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Reference in New Issue
Block a user