feat: add emoji reactor workshop (#61638)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jessica Wilkins <67210629+jdwilkin4@users.noreply.github.com>
This commit is contained in:
Ilenia
2025-09-26 16:10:57 +02:00
committed by GitHub
parent 71adf50f6a
commit 84f5d7375b
19 changed files with 2814 additions and 0 deletions

View File

@@ -3613,6 +3613,12 @@
"In this workshop, you will build a storytelling app that will allow you to list different stories based on genre."
]
},
"workshop-emoji-reactor": {
"title": "Build an Emoji Reactor",
"intro": [
"In this workshop, you will build an emoji reactor to practice <code>querySelector</code> and <code>querySelectorAll</code>."
]
},
"lab-favorite-icon-toggler": {
"title": "Build a Favorite Icon Toggler",
"intro": [

View File

@@ -0,0 +1,9 @@
---
title: Introduction to the Build an Emoji Reactor
block: workshop-emoji-reactor
superBlock: full-stack-developer
---
## Introduction to the Build an Emoji Reactor
In this workshop, you will build an emoji reactor to practice `querySelector` and `querySelectorAll`.

View File

@@ -0,0 +1,143 @@
---
id: 688c90634eb5ae69845ac35d
title: Step 1
challengeType: 0
dashedName: step-1
demoType: onLoad
---
# --description--
In this workshop you will create an Emoji Reactor App. The HTML boilerplate and all of the CSS has been provided for you.
Start by creating a `main` element.
Inside the `main` element create an `h1` element with a `class` of `title` and a text of `How are you feeling today?`.
# --hints--
You should have a `main` element.
```js
assert.exists(document.querySelector("main"));
```
You should have a `h1` as child of `main`.
```js
assert.exists(document.querySelector("main > h1"));
```
The `h1` element should have a class of `title`.
```js
assert.equal(document.querySelector("main > h1")?.className, "title");
```
The `h1` element should contain the text `How are you feeling today?`.
```js
assert.equal(document.querySelector("main > h1")?.textContent.trim(), "How are you feeling today?");
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Emoji Reactor</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
--fcc-editable-region--
--fcc-editable-region--
</body>
</html>
```
```css
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--light-grey: #efefef;
--white: #ffffff;
--very-dark-blue: #0a0a23;
--light-purple: #a78bfa;
--very-light-purple: #c4b5fd;
--purple: #8b5cf6;
}
body {
background-color: var(--very-dark-blue);
color: var(--light-grey);
font-family: sans-serif;
}
main {
text-align: center;
padding: 10px;
}
.btn-container,
button {
display: flex;
justify-content: space-evenly;
align-items: center;
}
.btn-container {
flex-direction: column;
}
.emoji-btn {
width: 70%;
cursor: pointer;
color: var(--white);
background-color: var(--light-purple);
background-image: linear-gradient(
to bottom,
var(--very-light-purple),
var(--light-purple)
);
border: 3px solid var(--purple);
border-radius: 8px;
padding: 10px;
font-size: 1.5rem;
margin: 10px 0;
transition: background-color 0.3s ease, transform 0.2s ease;
}
@media (min-width: 768px) {
.emoji-btn {
width: 30%;
}
}
.emoji-btn:hover {
background-color: var(--purple);
background-image: none;
}
.title {
margin-top: 15px;
font-size: 2rem;
}
.description {
font-size: 1.4rem;
margin: 20px 0;
}
```

View File

@@ -0,0 +1,137 @@
---
id: 6899b0d1825ff24e9fe8d747
title: Step 2
challengeType: 0
dashedName: step-2
---
# --description--
Below the `h1` element, add a `p` element with class `description`.
Inside the `p` element write the text `Click on the buttons below to rate your emotions.`.
# --hints--
You should create a new `p` element below the `h1` element.
```js
assert.exists(document.querySelector("h1 + p"));
```
The new `p` element should have a class of `description`.
```js
assert.equal(document.querySelector("h1 + p")?.className, "description");
```
The new `p` element should have text of `Click on the buttons below to rate your emotions.`.
```js
assert.equal(document.querySelector("h1 + p")?.textContent.trim(), "Click on the buttons below to rate your emotions.");
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Emoji Reactor</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<main>
--fcc-editable-region--
<h1 class="title">How are you feeling today?</h1>
--fcc-editable-region--
</main>
</body>
</html>
```
```css
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--light-grey: #efefef;
--white: #ffffff;
--very-dark-blue: #0a0a23;
--light-purple: #a78bfa;
--very-light-purple: #c4b5fd;
--purple: #8b5cf6;
}
body {
background-color: var(--very-dark-blue);
color: var(--light-grey);
font-family: sans-serif;
}
main {
text-align: center;
padding: 10px;
}
.btn-container,
button {
display: flex;
justify-content: space-evenly;
align-items: center;
}
.btn-container {
flex-direction: column;
}
.emoji-btn {
width: 70%;
cursor: pointer;
color: var(--white);
background-color: var(--light-purple);
background-image: linear-gradient(
to bottom,
var(--very-light-purple),
var(--light-purple)
);
border: 3px solid var(--purple);
border-radius: 8px;
padding: 10px;
font-size: 1.5rem;
margin: 10px 0;
transition: background-color 0.3s ease, transform 0.2s ease;
}
@media (min-width: 768px) {
.emoji-btn {
width: 30%;
}
}
.emoji-btn:hover {
background-color: var(--purple);
background-image: none;
}
.title {
margin-top: 15px;
font-size: 2rem;
}
.description {
font-size: 1.4rem;
margin: 20px 0;
}
```

View File

@@ -0,0 +1,162 @@
---
id: 6899b1d3bb656e56bd6937e2
title: Step 3
challengeType: 0
dashedName: step-3
---
# --description--
Below the `p` element, create a `div` element with the class `btn-container`.
Inside the `div` element, create a `button` element.
This `button` should have an `id` of `happy-btn`, a class of `emoji-btn` and an `aria-label` of `Happy face emoji`.
# --hints--
Create a new `div` element below the `p` element.
```js
assert.exists(document.querySelector("p + div"));
```
The new `div` element should have a class of `btn-container`.
```js
assert.equal(document.querySelector("p + div")?.className, "btn-container");
```
There should be a `button` element inside the `div` element.
```js
assert.exists(document.querySelector("div > button"));
```
The `button` element should have an `id` of `happy-btn`.
```js
assert.equal(document.querySelector("div > button")?.id, "happy-btn");
```
The `button` element should have a `class` of `emoji-btn`.
```js
assert.equal(document.querySelector("div > button")?.className, "emoji-btn");
```
The `button` element should have an `aria-label` of `Happy face emoji`.
```js
assert.equal(document.querySelector("div > button")?.getAttribute("aria-label"), "Happy face emoji");
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Emoji Reactor</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<main>
<h1 class="title">How are you feeling today?</h1>
<p class="description">
Click on the buttons below to rate your emotions.
</p>
--fcc-editable-region--
--fcc-editable-region--
</main>
</body>
</html>
```
```css
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--light-grey: #efefef;
--white: #ffffff;
--very-dark-blue: #0a0a23;
--light-purple: #a78bfa;
--very-light-purple: #c4b5fd;
--purple: #8b5cf6;
}
body {
background-color: var(--very-dark-blue);
color: var(--light-grey);
font-family: sans-serif;
}
main {
text-align: center;
padding: 10px;
}
.btn-container,
button {
display: flex;
justify-content: space-evenly;
align-items: center;
}
.btn-container {
flex-direction: column;
}
.emoji-btn {
width: 70%;
cursor: pointer;
color: var(--white);
background-color: var(--light-purple);
background-image: linear-gradient(
to bottom,
var(--very-light-purple),
var(--light-purple)
);
border: 3px solid var(--purple);
border-radius: 8px;
padding: 10px;
font-size: 1.5rem;
margin: 10px 0;
transition: background-color 0.3s ease, transform 0.2s ease;
}
@media (min-width: 768px) {
.emoji-btn {
width: 30%;
}
}
.emoji-btn:hover {
background-color: var(--purple);
background-image: none;
}
.title {
margin-top: 15px;
font-size: 2rem;
}
.description {
font-size: 1.4rem;
margin: 20px 0;
}
```

View File

@@ -0,0 +1,166 @@
---
id: 6899b593d232e07617f74055
title: Step 4
challengeType: 0
dashedName: step-4
---
# --description--
Inside the `button` element, create a `span` element that contains `😊`
Give to the `span` element a `role` attribute with a value of `img` and an `aria-hidden` attribute with a value of `true`.
Then, create a second `span` element with a `class` of `count` containing the text `0/10`.
# --hints--
Inside the `button` element there should be two `span` elements.
```js
assert.lengthOf(document.querySelectorAll("button > span"), 2);
```
The first `span` element should have a text content of `😊`.
```js
assert.equal(document.querySelectorAll("button > span")[0]?.textContent.trim(), "😊");
```
The first `span` element should have a `role` attribute with value of `img`.
```js
assert.equal(document.querySelectorAll("button > span")[0]?.getAttribute("role"), "img");
```
The first `span` element should have an `aria-hidden` attribute with value of `true`.
```js
assert.equal(document.querySelectorAll("button > span")[0]?.getAttribute("aria-hidden"), "true");
```
The second `span` element should have a `class` attribute with value of `count`.
```js
assert.equal(document.querySelectorAll("button > span")[1]?.className, "count");
```
The second `span` element should have a text content of `0/10`.
```js
assert.equal(document.querySelectorAll("button > span")[1]?.textContent.trim(), "0/10");
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Emoji Reactor</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<main>
<h1 class="title">How are you feeling today?</h1>
<p class="description">
Click on the buttons below to rate your emotions.
</p>
<div class="btn-container">
--fcc-editable-region--
<button id="happy-btn" class="emoji-btn" aria-label="Happy face emoji">
</button>
--fcc-editable-region--
</div>
</main>
</body>
</html>
```
```css
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--light-grey: #efefef;
--white: #ffffff;
--very-dark-blue: #0a0a23;
--light-purple: #a78bfa;
--very-light-purple: #c4b5fd;
--purple: #8b5cf6;
}
body {
background-color: var(--very-dark-blue);
color: var(--light-grey);
font-family: sans-serif;
}
main {
text-align: center;
padding: 10px;
}
.btn-container,
button {
display: flex;
justify-content: space-evenly;
align-items: center;
}
.btn-container {
flex-direction: column;
}
.emoji-btn {
width: 70%;
cursor: pointer;
color: var(--white);
background-color: var(--light-purple);
background-image: linear-gradient(
to bottom,
var(--very-light-purple),
var(--light-purple)
);
border: 3px solid var(--purple);
border-radius: 8px;
padding: 10px;
font-size: 1.5rem;
margin: 10px 0;
transition: background-color 0.3s ease, transform 0.2s ease;
}
@media (min-width: 768px) {
.emoji-btn {
width: 30%;
}
}
.emoji-btn:hover {
background-color: var(--purple);
background-image: none;
}
.title {
margin-top: 15px;
font-size: 2rem;
}
.description {
font-size: 1.4rem;
margin: 20px 0;
}
```

View File

@@ -0,0 +1,147 @@
---
id: 6899b7755876b10444ae3bcd
title: Step 5
challengeType: 0
dashedName: step-5
---
# --description--
Now it's time to link the JavaScript file.
Add a `script` element right before the closing tag of the `body` element with the right attribute and value to link the `script.js` file.
# --hints--
You should have a `script` element.
```js
assert.match(code, /<script[^>]*>\s*<\/script>/);
```
The `script` element should have a `src` of `./script.js`.
```js
assert.match(code, /<script\s*src\s*=\s*('|")(\.\/)?script\.js\1\s*>\s*<\/script>/);
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Emoji Reactor</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<main>
<h1 class="title">How are you feeling today?</h1>
<p class="description">
Click on the buttons below to rate your emotions.
</p>
<div class="btn-container">
<button id="happy-btn" class="emoji-btn" aria-label="Happy face emoji">
<span role="img" aria-hidden="true">😊</span>
<span class="count">0/10</span>
</button>
</div>
</main>
--fcc-editable-region--
--fcc-editable-region--
</body>
</html>
```
```css
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--light-grey: #efefef;
--white: #ffffff;
--very-dark-blue: #0a0a23;
--light-purple: #a78bfa;
--very-light-purple: #c4b5fd;
--purple: #8b5cf6;
}
body {
background-color: var(--very-dark-blue);
color: var(--light-grey);
font-family: sans-serif;
}
main {
text-align: center;
padding: 10px;
}
.btn-container,
button {
display: flex;
justify-content: space-evenly;
align-items: center;
}
.btn-container {
flex-direction: column;
}
.emoji-btn {
width: 70%;
cursor: pointer;
color: var(--white);
background-color: var(--light-purple);
background-image: linear-gradient(
to bottom,
var(--very-light-purple),
var(--light-purple)
);
border: 3px solid var(--purple);
border-radius: 8px;
padding: 10px;
font-size: 1.5rem;
margin: 10px 0;
transition: background-color 0.3s ease, transform 0.2s ease;
}
@media (min-width: 768px) {
.emoji-btn {
width: 30%;
}
}
.emoji-btn:hover {
background-color: var(--purple);
background-image: none;
}
.title {
margin-top: 15px;
font-size: 2rem;
}
.description {
font-size: 1.4rem;
margin: 20px 0;
}
```
```js
```

View File

@@ -0,0 +1,146 @@
---
id: 6899b84e392df30ae370985e
title: Step 6
challengeType: 0
dashedName: step-6
---
# --description--
Now, in the JavaScript file, create an `happyBtn` variable.
Use `querySelector` to store a reference to the `#happy-btn` element in the `happyBtn` variable.
# --hints--
You should have a variable named `happyBtn`.
```js
assert.exists(happyBtn);
```
The `happyBtn` variable should hold a reference to the `#happy-btn` element.
```js
assert.equal(happyBtn, document.querySelector("#happy-btn"));
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Emoji Reactor</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<main>
<h1 class="title">How are you feeling today?</h1>
<p class="description">
Click on the buttons below to rate your emotions.
</p>
<div class="btn-container">
<button id="happy-btn" class="emoji-btn" aria-label="Happy face emoji">
<span role="img" aria-hidden="true">😊</span>
<span class="count">0/10</span>
</button>
</div>
</main>
<script src="./script.js"></script>
</body>
</html>
```
```css
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--light-grey: #efefef;
--white: #ffffff;
--very-dark-blue: #0a0a23;
--light-purple: #a78bfa;
--very-light-purple: #c4b5fd;
--purple: #8b5cf6;
}
body {
background-color: var(--very-dark-blue);
color: var(--light-grey);
font-family: sans-serif;
}
main {
text-align: center;
padding: 10px;
}
.btn-container,
button {
display: flex;
justify-content: space-evenly;
align-items: center;
}
.btn-container {
flex-direction: column;
}
.emoji-btn {
width: 70%;
cursor: pointer;
color: var(--white);
background-color: var(--light-purple);
background-image: linear-gradient(
to bottom,
var(--very-light-purple),
var(--light-purple)
);
border: 3px solid var(--purple);
border-radius: 8px;
padding: 10px;
font-size: 1.5rem;
margin: 10px 0;
transition: background-color 0.3s ease, transform 0.2s ease;
}
@media (min-width: 768px) {
.emoji-btn {
width: 30%;
}
}
.emoji-btn:hover {
background-color: var(--purple);
background-image: none;
}
.title {
margin-top: 15px;
font-size: 2rem;
}
.description {
font-size: 1.4rem;
margin: 20px 0;
}
```
```js
--fcc-editable-region--
--fcc-editable-region--
```

View File

@@ -0,0 +1,145 @@
---
id: 6899c30b1d26094e11170c92
title: Step 7
challengeType: 0
dashedName: step-7
---
# --description--
Now you need to add an event listener on the `happyBtn` element.
Write the event listener and its callback so that when the button is clicked the app will log to the console `Button clicked!`.
# --hints--
When the `happyBtn` is clicked, `Button clicked!` should be logged to the console.
```js
const spy = __helpers.spyOn(console, "log");
document.querySelector(`#happy-btn`).click();
assert.sameDeepOrderedMembers(spy.calls, [["Button clicked!"]]);
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Emoji Reactor</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<main>
<h1 class="title">How are you feeling today?</h1>
<p class="description">
Click on the buttons below to rate your emotions.
</p>
<div class="btn-container">
<button id="happy-btn" class="emoji-btn" aria-label="Happy face emoji">
<span role="img" aria-hidden="true">😊</span>
<span class="count">0/10</span>
</button>
</div>
</main>
<script src="./script.js"></script>
</body>
</html>
```
```css
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--light-grey: #efefef;
--white: #ffffff;
--very-dark-blue: #0a0a23;
--light-purple: #a78bfa;
--very-light-purple: #c4b5fd;
--purple: #8b5cf6;
}
body {
background-color: var(--very-dark-blue);
color: var(--light-grey);
font-family: sans-serif;
}
main {
text-align: center;
padding: 10px;
}
.btn-container,
button {
display: flex;
justify-content: space-evenly;
align-items: center;
}
.btn-container {
flex-direction: column;
}
.emoji-btn {
width: 70%;
cursor: pointer;
color: var(--white);
background-color: var(--light-purple);
background-image: linear-gradient(
to bottom,
var(--very-light-purple),
var(--light-purple)
);
border: 3px solid var(--purple);
border-radius: 8px;
padding: 10px;
font-size: 1.5rem;
margin: 10px 0;
transition: background-color 0.3s ease, transform 0.2s ease;
}
@media (min-width: 768px) {
.emoji-btn {
width: 30%;
}
}
.emoji-btn:hover {
background-color: var(--purple);
background-image: none;
}
.title {
margin-top: 15px;
font-size: 2rem;
}
.description {
font-size: 1.4rem;
margin: 20px 0;
}
```
```js
--fcc-editable-region--
const happyBtn = document.querySelector("#happy-btn");
--fcc-editable-region--
```

View File

@@ -0,0 +1,153 @@
---
id: 689af0bf1c707336ee9a1842
title: Step 8
challengeType: 0
dashedName: step-8
---
# --description--
Now replace the content of the event listener callback.
Use `querySelector` to find the `.count` element within the button.
Then log the text content of the `.count` element when the button is clicked.
# --hints--
You should log the text content of the `.count` element inside the clicked button.
```js
const spy = __helpers.spyOn(console, "log");
const testString = "teesting";
document.querySelector("#happy-btn .count").textContent = testString;
document.querySelector(`#happy-btn`).click();
assert.sameDeepOrderedMembers(spy.calls, [[testString]]);
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Emoji Reactor</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<main>
<h1 class="title">How are you feeling today?</h1>
<p class="description">
Click on the buttons below to rate your emotions.
</p>
<div class="btn-container">
<button id="happy-btn" class="emoji-btn" aria-label="Happy face emoji">
<span role="img" aria-hidden="true">😊</span>
<span class="count">0/10</span>
</button>
</div>
</main>
<script src="./script.js"></script>
</body>
</html>
```
```css
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--light-grey: #efefef;
--white: #ffffff;
--very-dark-blue: #0a0a23;
--light-purple: #a78bfa;
--very-light-purple: #c4b5fd;
--purple: #8b5cf6;
}
body {
background-color: var(--very-dark-blue);
color: var(--light-grey);
font-family: sans-serif;
}
main {
text-align: center;
padding: 10px;
}
.btn-container,
button {
display: flex;
justify-content: space-evenly;
align-items: center;
}
.btn-container {
flex-direction: column;
}
.emoji-btn {
width: 70%;
cursor: pointer;
color: var(--white);
background-color: var(--light-purple);
background-image: linear-gradient(
to bottom,
var(--very-light-purple),
var(--light-purple)
);
border: 3px solid var(--purple);
border-radius: 8px;
padding: 10px;
font-size: 1.5rem;
margin: 10px 0;
transition: background-color 0.3s ease, transform 0.2s ease;
}
@media (min-width: 768px) {
.emoji-btn {
width: 30%;
}
}
.emoji-btn:hover {
background-color: var(--purple);
background-image: none;
}
.title {
margin-top: 15px;
font-size: 2rem;
}
.description {
font-size: 1.4rem;
margin: 20px 0;
}
```
```js
--fcc-editable-region--
const happyBtn = document.querySelector("#happy-btn");
happyBtn.addEventListener("click", () => {
console.log("Button clicked!");
})
--fcc-editable-region--
```

View File

@@ -0,0 +1,173 @@
---
id: 689b15aacce1ae176ec768dc
title: Step 9
challengeType: 0
dashedName: step-9
---
# --description--
Now, you need to get the first number in the `0/10` text, in a way that will work even for `5/10` or `10/10`.
Parse the text content of the `.count` element to extract the current number.
Convert the count from a string to a number.
Log the current count in this format: `console.log("Current count:", currCount)`.
Hint: remember you can use the `split` method to divide a string into an array of substrings.
# --hints--
You should log the current count as a number.
```js
const spy = __helpers.spyOn(console, "log");
document.querySelector(`#happy-btn`).click();
assert.sameDeepOrderedMembers(spy.calls[0], ["Current count:", 0]);
```
You should log the current count as a number in a way that works for the various possible values.
```js
const spy = __helpers.spyOn(console, "log");
const testString = "5/10";
document.querySelector("#happy-btn .count").textContent = testString;
document.querySelector(`#happy-btn`).click();
assert.sameDeepOrderedMembers(spy.calls, [["Current count:", 5]]);
const testString2 = "10/10";
document.querySelector("#happy-btn .count").textContent = testString2;
document.querySelector(`#happy-btn`).click();
assert.sameDeepOrderedMembers(spy.calls[1], ["Current count:", 10]);
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Emoji Reactor</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<main>
<h1 class="title">How are you feeling today?</h1>
<p class="description">
Click on the buttons below to rate your emotions.
</p>
<div class="btn-container">
<button id="happy-btn" class="emoji-btn" aria-label="Happy face emoji">
<span role="img" aria-hidden="true">😊</span>
<span class="count">0/10</span>
</button>
</div>
</main>
<script src="./script.js"></script>
</body>
</html>
```
```css
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--light-grey: #efefef;
--white: #ffffff;
--very-dark-blue: #0a0a23;
--light-purple: #a78bfa;
--very-light-purple: #c4b5fd;
--purple: #8b5cf6;
}
body {
background-color: var(--very-dark-blue);
color: var(--light-grey);
font-family: sans-serif;
}
main {
text-align: center;
padding: 10px;
}
.btn-container,
button {
display: flex;
justify-content: space-evenly;
align-items: center;
}
.btn-container {
flex-direction: column;
}
.emoji-btn {
width: 70%;
cursor: pointer;
color: var(--white);
background-color: var(--light-purple);
background-image: linear-gradient(
to bottom,
var(--very-light-purple),
var(--light-purple)
);
border: 3px solid var(--purple);
border-radius: 8px;
padding: 10px;
font-size: 1.5rem;
margin: 10px 0;
transition: background-color 0.3s ease, transform 0.2s ease;
}
@media (min-width: 768px) {
.emoji-btn {
width: 30%;
}
}
.emoji-btn:hover {
background-color: var(--purple);
background-image: none;
}
.title {
margin-top: 15px;
font-size: 2rem;
}
.description {
font-size: 1.4rem;
margin: 20px 0;
}
```
```js
--fcc-editable-region--
const happyBtn = document.querySelector("#happy-btn");
happyBtn.addEventListener("click", () => {
const countEl = happyBtn.querySelector(".count");
console.log(countEl.textContent);
})
--fcc-editable-region--
```

View File

@@ -0,0 +1,176 @@
---
id: 689b17e7e63b8e2c13839e98
title: Step 10
challengeType: 0
dashedName: step-10
---
# --description--
Now it's time to implement the actual counting functionality.
Instead of just logging the current count, you need to increment it and update the display.
Remove the `console.log`.
Check if the current first number inside the `.count` is already 10 (the text is `10/10`), and if so, do nothing.
If the number is less then 10, increment the current count by 1 and update the text of the `.count` element. For example, if the current count is 2, it should be incremented to 3 and the text for the `.count` element should be `3/10`.
# --hints--
When the button is clicked, the count should increment from 0 to 1.
```js
const spy = __helpers.spyOn(console, "log");
const countEl = document.querySelector("#happy-btn .count");
countEl.textContent = "0/10";
document.querySelector("#happy-btn").click();
assert.equal(countEl.textContent, "1/10");
```
When the button is clicked multiple times, the count should increment properly.
```js
const countEl = document.querySelector("#happy-btn .count");
countEl.textContent = "3/10";
document.querySelector("#happy-btn").click();
assert.equal(countEl.textContent, "4/10");
```
When the count is already at 10, clicking should not increment it further.
```js
const countEl = document.querySelector("#happy-btn .count");
countEl.textContent = "10/10";
document.querySelector("#happy-btn").click();
assert.equal(countEl.textContent, "10/10");
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Emoji Reactor</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<main>
<h1 class="title">How are you feeling today?</h1>
<p class="description">
Click on the buttons below to rate your emotions.
</p>
<div class="btn-container">
<button id="happy-btn" class="emoji-btn" aria-label="Happy face emoji">
<span role="img" aria-hidden="true">😊</span>
<span class="count">0/10</span>
</button>
</div>
</main>
<script src="./script.js"></script>
</body>
</html>
```
```css
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--light-grey: #efefef;
--white: #ffffff;
--very-dark-blue: #0a0a23;
--light-purple: #a78bfa;
--very-light-purple: #c4b5fd;
--purple: #8b5cf6;
}
body {
background-color: var(--very-dark-blue);
color: var(--light-grey);
font-family: sans-serif;
}
main {
text-align: center;
padding: 10px;
}
.btn-container,
button {
display: flex;
justify-content: space-evenly;
align-items: center;
}
.btn-container {
flex-direction: column;
}
.emoji-btn {
width: 70%;
cursor: pointer;
color: var(--white);
background-color: var(--light-purple);
background-image: linear-gradient(
to bottom,
var(--very-light-purple),
var(--light-purple)
);
border: 3px solid var(--purple);
border-radius: 8px;
padding: 10px;
font-size: 1.5rem;
margin: 10px 0;
transition: background-color 0.3s ease, transform 0.2s ease;
}
@media (min-width: 768px) {
.emoji-btn {
width: 30%;
}
}
.emoji-btn:hover {
background-color: var(--purple);
background-image: none;
}
.title {
margin-top: 15px;
font-size: 2rem;
}
.description {
font-size: 1.4rem;
margin: 20px 0;
}
```
```js
--fcc-editable-region--
const happyBtn = document.querySelector("#happy-btn");
happyBtn.addEventListener("click", () => {
const countEl = happyBtn.querySelector(".count");
const currCount = +countEl.textContent.split("/")[0];
console.log("Current count:", currCount);
})
--fcc-editable-region--
```

View File

@@ -0,0 +1,181 @@
---
id: 68a9f8378ddba1261a268cce
title: Step 11
challengeType: 0
dashedName: step-11
---
# --description--
You can make the code more reusable.
Create a function called `updateCount` that takes a button element as a parameter.
This function should contain all the logic for updating a button's count: finding the count element, parsing the current count, checking if it's at the maximum, incrementing, and updating the display.
Then update your event listener callback to call `updateCount(happyBtn)` instead of having the logic inline.
# --hints--
You should create a function named `updateCount`.
```js
assert.isFunction(updateCount);
```
The `updateCount` function should take a button parameter.
```js
assert.equal(updateCount.length, 1);
```
The `updateCount` function should work correctly with any button element.
```js
const testBtn = document.createElement("button");
testBtn.innerHTML = '<span class="count">3/10</span>';
updateCount(testBtn);
assert.equal(testBtn.querySelector(".count").textContent, "4/10");
```
Your event listener should call `updateCount` with the button as an argument.
```js
const spy = __helpers.spyOn(window, "updateCount");
document.querySelector("#happy-btn").click();
assert.equal(spy.calls.length, 1);
assert.equal(spy.calls[0][0], document.querySelector("#happy-btn"));
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Emoji Reactor</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<main>
<h1 class="title">How are you feeling today?</h1>
<p class="description">
Click on the buttons below to rate your emotions.
</p>
<div class="btn-container">
<button id="happy-btn" class="emoji-btn" aria-label="Happy face emoji">
<span role="img" aria-hidden="true">😊</span>
<span class="count">0/10</span>
</button>
</div>
</main>
<script src="./script.js"></script>
</body>
</html>
```
```css
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--light-grey: #efefef;
--white: #ffffff;
--very-dark-blue: #0a0a23;
--light-purple: #a78bfa;
--very-light-purple: #c4b5fd;
--purple: #8b5cf6;
}
body {
background-color: var(--very-dark-blue);
color: var(--light-grey);
font-family: sans-serif;
}
main {
text-align: center;
padding: 10px;
}
.btn-container,
button {
display: flex;
justify-content: space-evenly;
align-items: center;
}
.btn-container {
flex-direction: column;
}
.emoji-btn {
width: 70%;
cursor: pointer;
color: var(--white);
background-color: var(--light-purple);
background-image: linear-gradient(
to bottom,
var(--very-light-purple),
var(--light-purple)
);
border: 3px solid var(--purple);
border-radius: 8px;
padding: 10px;
font-size: 1.5rem;
margin: 10px 0;
transition: background-color 0.3s ease, transform 0.2s ease;
}
@media (min-width: 768px) {
.emoji-btn {
width: 30%;
}
}
.emoji-btn:hover {
background-color: var(--purple);
background-image: none;
}
.title {
margin-top: 15px;
font-size: 2rem;
}
.description {
font-size: 1.4rem;
margin: 20px 0;
}
```
```js
--fcc-editable-region--
const happyBtn = document.querySelector("#happy-btn");
happyBtn.addEventListener("click", () => {
const countEl = happyBtn.querySelector(".count");
let currCount = +countEl.textContent.split("/")[0];
if (currCount === 10) return;
currCount++;
countEl.textContent = `${currCount}/10`;
})
--fcc-editable-region--
```

View File

@@ -0,0 +1,234 @@
---
id: 68a9fa161498c3324ac06fe1
title: Step 12
challengeType: 0
dashedName: step-12
---
# --description--
It's time to start working on the other buttons. The remaining `button` elements have been added for you in the HTML file.
For each new button (`#confused-btn`, `#sad-btn` and `#loving-btn`), select it using `querySelector` with its ID, then add a click event listener that calls `updateCount` with that button.
Use the variable names `confusedBtn`, `sadBtn`, `lovingBtn`.
# --hints--
You should create a variable named `confusedBtn`.
```js
assert.exists(confusedBtn);
```
You should store the `#confused-btn` element in the `confusedBtn` variable.
```js
assert.equal(confusedBtn, document.querySelector('#confused-btn'));
```
You should create a variable named `sadBtn`.
```js
assert.exists(sadBtn);
```
You should store the `#sad-btn` element in the `sadBtn` variable.
```js
assert.equal(sadBtn, document.querySelector('#sad-btn'));
```
You should create a variable named `lovingBtn`.
```js
assert.exists(lovingBtn);
```
You should store the `#loving-btn` element in the `lovingBtn` variable.
```js
assert.equal(lovingBtn, document.querySelector('#loving-btn'));
```
The `#confused-btn` element should have a click event listener that calls `updateCount`.
```js
const spy = __helpers.spyOn(window, "updateCount");
document.querySelector("#confused-btn").click();
assert.equal(spy.calls.length, 1);
assert.equal(spy.calls[0][0], document.querySelector("#confused-btn"));
```
The `#sad-btn` element should have a click event listener that calls `updateCount`.
```js
const spy = __helpers.spyOn(window, "updateCount");
document.querySelector("#sad-btn").click();
assert.equal(spy.calls.length, 1);
assert.equal(spy.calls[0][0], document.querySelector("#sad-btn"));
```
The `#loving-btn` element should have a click event listener that calls `updateCount`.
```js
const spy = __helpers.spyOn(window, "updateCount");
document.querySelector("#loving-btn").click();
assert.equal(spy.calls.length, 1);
assert.equal(spy.calls[0][0], document.querySelector("#loving-btn"));
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Emoji Reactor</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<main>
<h1 class="title">How are you feeling today?</h1>
<p class="description">
Click on the buttons below to rate your emotions.
</p>
<div class="btn-container">
<button id="happy-btn" class="emoji-btn" aria-label="Happy face emoji">
<span role="img" aria-hidden="true">😊</span>
<span class="count">0/10</span>
</button>
<button
id="confused-btn"
class="emoji-btn"
aria-label="Confused face emoji"
>
<span role="img" aria-hidden="true">😕</span>
<span class="count">0/10</span>
</button>
<button id="sad-btn" class="emoji-btn" aria-label="Angry face emoji">
<span role="img" aria-hidden="true">😠</span>
<span class="count">0/10</span>
</button>
<button
id="loving-btn"
class="emoji-btn"
aria-label="Loving face emoji"
>
<span role="img" aria-hidden="true">😍</span>
<span class="count">0/10</span>
</button>
</div>
</main>
<script src="./script.js"></script>
</body>
</html>
```
```css
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--light-grey: #efefef;
--white: #ffffff;
--very-dark-blue: #0a0a23;
--light-purple: #a78bfa;
--very-light-purple: #c4b5fd;
--purple: #8b5cf6;
}
body {
background-color: var(--very-dark-blue);
color: var(--light-grey);
font-family: sans-serif;
}
main {
text-align: center;
padding: 10px;
}
.btn-container,
button {
display: flex;
justify-content: space-evenly;
align-items: center;
}
.btn-container {
flex-direction: column;
}
.emoji-btn {
width: 70%;
cursor: pointer;
color: var(--white);
background-color: var(--light-purple);
background-image: linear-gradient(
to bottom,
var(--very-light-purple),
var(--light-purple)
);
border: 3px solid var(--purple);
border-radius: 8px;
padding: 10px;
font-size: 1.5rem;
margin: 10px 0;
transition: background-color 0.3s ease, transform 0.2s ease;
}
@media (min-width: 768px) {
.emoji-btn {
width: 30%;
}
}
.emoji-btn:hover {
background-color: var(--purple);
background-image: none;
}
.title {
margin-top: 15px;
font-size: 2rem;
}
.description {
font-size: 1.4rem;
margin: 20px 0;
}
```
```js
--fcc-editable-region--
function updateCount(btn) {
const countEl = btn.querySelector(".count");
let currCount = +countEl.textContent.split("/")[0];
if (currCount === 10) return;
currCount++;
countEl.textContent = `${currCount}/10`;
}
const happyBtn = document.querySelector("#happy-btn");
happyBtn.addEventListener("click", () => updateCount(happyBtn));
--fcc-editable-region--
```

View File

@@ -0,0 +1,209 @@
---
id: 68a9fa1787009f3293b7ba7f
title: Step 13
challengeType: 0
dashedName: step-13
---
# --description--
You've probably noticed that your code is getting quite repetitive! There's a better way to handle multiple similar elements.
Instead of selecting each button individually, use `querySelectorAll(".emoji-btn")` to select all buttons with the class `emoji-btn` at once. Store the result in a variable called `btns`.
# --before-all--
```js
const loggedValues = [];
const originalConsoleLog = console.log;
console.log = (...args) => {
loggedValues.push(args);
originalConsoleLog(...args);
};
```
# --hints--
You should use `querySelectorAll` to select all emoji buttons.
```js
assert.match(code, /document\.querySelectorAll\s*\(\s*['"`]\.emoji-btn['"`]\s*\)/);
```
You should store the result in a variable called `btns`.
```js
assert.isDefined(btns, 'You should create a variable called btns');
assert.isTrue(btns instanceof NodeList, 'btns should be a NodeList from querySelectorAll');
```
The `btns` variable should contain all 4 emoji buttons.
```js
assert.equal(btns.length, 4, 'btns should contain all 4 emoji buttons');
assert.equal(btns[0].id, 'happy-btn', 'First button should be the happy button');
assert.equal(btns[1].id, 'confused-btn', 'Second button should be the confused button');
assert.equal(btns[2].id, 'sad-btn', 'Third button should be the sad button');
assert.equal(btns[3].id, 'loving-btn', 'Fourth button should be the loving button');
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Emoji Reactor</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<main>
<h1 class="title">How are you feeling today?</h1>
<p class="description">
Click on the buttons below to rate your emotions.
</p>
<div class="btn-container">
<button id="happy-btn" class="emoji-btn" aria-label="Happy face emoji">
<span role="img" aria-hidden="true">😊</span>
<span class="count">0/10</span>
</button>
<button
id="confused-btn"
class="emoji-btn"
aria-label="Confused face emoji"
>
<span role="img" aria-hidden="true">😕</span>
<span class="count">0/10</span>
</button>
<button id="sad-btn" class="emoji-btn" aria-label="Angry face emoji">
<span role="img" aria-hidden="true">😠</span>
<span class="count">0/10</span>
</button>
<button
id="loving-btn"
class="emoji-btn"
aria-label="Loving face emoji"
>
<span role="img" aria-hidden="true">😍</span>
<span class="count">0/10</span>
</button>
</div>
</main>
<script src="./script.js"></script>
</body>
</html>
```
```css
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--light-grey: #efefef;
--white: #ffffff;
--very-dark-blue: #0a0a23;
--light-purple: #a78bfa;
--very-light-purple: #c4b5fd;
--purple: #8b5cf6;
}
body {
background-color: var(--very-dark-blue);
color: var(--light-grey);
font-family: sans-serif;
}
main {
text-align: center;
padding: 10px;
}
.btn-container,
button {
display: flex;
justify-content: space-evenly;
align-items: center;
}
.btn-container {
flex-direction: column;
}
.emoji-btn {
width: 70%;
cursor: pointer;
color: var(--white);
background-color: var(--light-purple);
background-image: linear-gradient(
to bottom,
var(--very-light-purple),
var(--light-purple)
);
border: 3px solid var(--purple);
border-radius: 8px;
padding: 10px;
font-size: 1.5rem;
margin: 10px 0;
transition: background-color 0.3s ease, transform 0.2s ease;
}
@media (min-width: 768px) {
.emoji-btn {
width: 30%;
}
}
.emoji-btn:hover {
background-color: var(--purple);
background-image: none;
}
.title {
margin-top: 15px;
font-size: 2rem;
}
.description {
font-size: 1.4rem;
margin: 20px 0;
}
```
```js
--fcc-editable-region--
function updateCount(btn) {
const countEl = btn.querySelector(".count");
let currCount = +countEl.textContent.split("/")[0];
if (currCount === 10) return;
currCount++;
countEl.textContent = `${currCount}/10`;
}
const happyBtn = document.querySelector("#happy-btn");
const confusedBtn = document.querySelector("#confused-btn");
const sadBtn = document.querySelector("#sad-btn");
const lovingBtn = document.querySelector("#loving-btn");
happyBtn.addEventListener("click", () => updateCount(happyBtn));
confusedBtn.addEventListener("click", () => updateCount(confusedBtn));
sadBtn.addEventListener("click", () => updateCount(sadBtn));
lovingBtn.addEventListener("click", () => updateCount(lovingBtn));
--fcc-editable-region--
```

View File

@@ -0,0 +1,336 @@
---
id: 68a9fa18ad7a8432d0fc8621
title: Step 15
challengeType: 0
dashedName: step-15
---
# --description--
In the lectures you learned that `querySelectorAll` returns a `NodeList`, which is an array-like structure, and one of the methods that a `NodeList` has is `forEach()`, and it works the same way as the `forEach` that exists on arrays.
Iterate over `btns` with a `forEach()` that adds the same event listener to each button.
Use a callback function that takes a `btn` parameter, and inside the callback, add a click event listener that calls `updateCount(btn)`.
With this you have finished the workshop.
# --hints--
You should use `btns.forEach()` to iterate over the buttons.
```js
assert.match(code, /btns\.forEach\s*\(/);
```
All buttons should have event listeners that call `updateCount` when clicked.
```js
// Test that clicking each button calls updateCount
const spy = __helpers.spyOn(window, "updateCount");
document.querySelector("#happy-btn").click();
document.querySelector("#confused-btn").click();
document.querySelector("#sad-btn").click();
document.querySelector("#loving-btn").click();
assert.lengthOf(spy.calls, 4);
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Emoji Reactor</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<main>
<h1 class="title">How are you feeling today?</h1>
<p class="description">
Click on the buttons below to rate your emotions.
</p>
<div class="btn-container">
<button id="happy-btn" class="emoji-btn" aria-label="Happy face emoji">
<span role="img" aria-hidden="true">😊</span>
<span class="count">0/10</span>
</button>
<button
id="confused-btn"
class="emoji-btn"
aria-label="Confused face emoji"
>
<span role="img" aria-hidden="true">😕</span>
<span class="count">0/10</span>
</button>
<button id="sad-btn" class="emoji-btn" aria-label="Angry face emoji">
<span role="img" aria-hidden="true">😠</span>
<span class="count">0/10</span>
</button>
<button
id="loving-btn"
class="emoji-btn"
aria-label="Loving face emoji"
>
<span role="img" aria-hidden="true">😍</span>
<span class="count">0/10</span>
</button>
</div>
</main>
<script src="./script.js"></script>
</body>
</html>
```
```css
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--light-grey: #efefef;
--white: #ffffff;
--very-dark-blue: #0a0a23;
--light-purple: #a78bfa;
--very-light-purple: #c4b5fd;
--purple: #8b5cf6;
}
body {
background-color: var(--very-dark-blue);
color: var(--light-grey);
font-family: sans-serif;
}
main {
text-align: center;
padding: 10px;
}
.btn-container,
button {
display: flex;
justify-content: space-evenly;
align-items: center;
}
.btn-container {
flex-direction: column;
}
.emoji-btn {
width: 70%;
cursor: pointer;
color: var(--white);
background-color: var(--light-purple);
background-image: linear-gradient(
to bottom,
var(--very-light-purple),
var(--light-purple)
);
border: 3px solid var(--purple);
border-radius: 8px;
padding: 10px;
font-size: 1.5rem;
margin: 10px 0;
transition: background-color 0.3s ease, transform 0.2s ease;
}
@media (min-width: 768px) {
.emoji-btn {
width: 30%;
}
}
.emoji-btn:hover {
background-color: var(--purple);
background-image: none;
}
.title {
margin-top: 15px;
font-size: 2rem;
}
.description {
font-size: 1.4rem;
margin: 20px 0;
}
```
```js
function updateCount(btn) {
const countEl = btn.querySelector(".count");
let currCount = +countEl.textContent.split("/")[0];
if (currCount === 10) return;
currCount++;
countEl.textContent = `${currCount}/10`;
}
--fcc-editable-region--
const btns = document.querySelectorAll(".emoji-btn");
--fcc-editable-region--
```
# --solutions--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Emoji Reactor</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<main>
<h1 class="title">How are you feeling today?</h1>
<p class="description">
Click on the buttons below to rate your emotions.
</p>
<div class="btn-container">
<button id="happy-btn" class="emoji-btn" aria-label="Happy face emoji">
<span role="img" aria-hidden="true">😊</span>
<span class="count">0/10</span>
</button>
<button
id="confused-btn"
class="emoji-btn"
aria-label="Confused face emoji"
>
<span role="img" aria-hidden="true">😕</span>
<span class="count">0/10</span>
</button>
<button id="sad-btn" class="emoji-btn" aria-label="Angry face emoji">
<span role="img" aria-hidden="true">😠</span>
<span class="count">0/10</span>
</button>
<button
id="loving-btn"
class="emoji-btn"
aria-label="Loving face emoji"
>
<span role="img" aria-hidden="true">😍</span>
<span class="count">0/10</span>
</button>
</div>
</main>
<script src="./script.js"></script>
</body>
</html>
```
```css
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--light-grey: #efefef;
--white: #ffffff;
--very-dark-blue: #0a0a23;
--light-purple: #a78bfa;
--very-light-purple: #c4b5fd;
--purple: #8b5cf6;
}
body {
background-color: var(--very-dark-blue);
color: var(--light-grey);
font-family: sans-serif;
}
main {
text-align: center;
padding: 10px;
}
.btn-container,
button {
display: flex;
justify-content: space-evenly;
align-items: center;
}
.btn-container {
flex-direction: column;
}
.emoji-btn {
width: 70%;
cursor: pointer;
color: var(--white);
background-color: var(--light-purple);
background-image: linear-gradient(
to bottom,
var(--very-light-purple),
var(--light-purple)
);
border: 3px solid var(--purple);
border-radius: 8px;
padding: 10px;
font-size: 1.5rem;
margin: 10px 0;
transition: background-color 0.3s ease, transform 0.2s ease;
}
@media (min-width: 768px) {
.emoji-btn {
width: 30%;
}
}
.emoji-btn:hover {
background-color: var(--purple);
background-image: none;
}
.title {
margin-top: 15px;
font-size: 2rem;
}
.description {
font-size: 1.4rem;
margin: 20px 0;
}
```
```js
function updateCount(btn) {
const countEl = btn.querySelector(".count");
let currCount = +countEl.textContent.split("/")[0];
if (currCount === 10) return;
currCount++;
countEl.textContent = `${currCount}/10`;
}
const btns = document.querySelectorAll(".emoji-btn");
btns.forEach((btn) => btn.addEventListener("click", () => updateCount(btn)));
```

View File

@@ -0,0 +1,218 @@
---
id: 68a9fa1976616e330813a96c
title: Step 14
challengeType: 0
dashedName: step-14
---
# --description--
Now make some space, remove all the button variables and the `eventListener` you have created for each.
# --hints--
The `happyBtn` variable should not exist.
```js
try {
happyBtn;
assert.fail('happyBtn variable should not exist');
} catch (e) {
assert.equal(e.name, 'ReferenceError', 'happyBtn variable should not exist');
}
```
The `confusedBtn` variable should not exist.
```js
try {
confusedBtn;
assert.fail('confusedBtn variable should not exist');
} catch (e) {
assert.equal(e.name, 'ReferenceError', 'confusedBtn variable should not exist');
}
```
The `saddBtn` variable should not exist.
```js
try {
sadBtn;
assert.fail('sadBtn variable should not exist');
} catch (e) {
assert.equal(e.name, 'ReferenceError', 'sadBtn variable should not exist');
}
```
The `lovingBtn` variable should not exist.
```js
try {
lovingBtn;
assert.fail('lovingBtn variable should not exist');
} catch (e) {
assert.equal(e.name, 'ReferenceError', 'lovingBtn variable should not exist');
}
```
# --seed--
## --seed-contents--
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Emoji Reactor</title>
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<main>
<h1 class="title">How are you feeling today?</h1>
<p class="description">
Click on the buttons below to rate your emotions.
</p>
<div class="btn-container">
<button id="happy-btn" class="emoji-btn" aria-label="Happy face emoji">
<span role="img" aria-hidden="true">😊</span>
<span class="count">0/10</span>
</button>
<button
id="confused-btn"
class="emoji-btn"
aria-label="Confused face emoji"
>
<span role="img" aria-hidden="true">😕</span>
<span class="count">0/10</span>
</button>
<button id="sad-btn" class="emoji-btn" aria-label="Angry face emoji">
<span role="img" aria-hidden="true">😠</span>
<span class="count">0/10</span>
</button>
<button
id="loving-btn"
class="emoji-btn"
aria-label="Loving face emoji"
>
<span role="img" aria-hidden="true">😍</span>
<span class="count">0/10</span>
</button>
</div>
</main>
<script src="./script.js"></script>
</body>
</html>
```
```css
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--light-grey: #efefef;
--white: #ffffff;
--very-dark-blue: #0a0a23;
--light-purple: #a78bfa;
--very-light-purple: #c4b5fd;
--purple: #8b5cf6;
}
body {
background-color: var(--very-dark-blue);
color: var(--light-grey);
font-family: sans-serif;
}
main {
text-align: center;
padding: 10px;
}
.btn-container,
button {
display: flex;
justify-content: space-evenly;
align-items: center;
}
.btn-container {
flex-direction: column;
}
.emoji-btn {
width: 70%;
cursor: pointer;
color: var(--white);
background-color: var(--light-purple);
background-image: linear-gradient(
to bottom,
var(--very-light-purple),
var(--light-purple)
);
border: 3px solid var(--purple);
border-radius: 8px;
padding: 10px;
font-size: 1.5rem;
margin: 10px 0;
transition: background-color 0.3s ease, transform 0.2s ease;
}
@media (min-width: 768px) {
.emoji-btn {
width: 30%;
}
}
.emoji-btn:hover {
background-color: var(--purple);
background-image: none;
}
.title {
margin-top: 15px;
font-size: 2rem;
}
.description {
font-size: 1.4rem;
margin: 20px 0;
}
```
```js
function updateCount(btn) {
const countEl = btn.querySelector(".count");
let currCount = +countEl.textContent.split("/")[0];
if (currCount === 10) return;
currCount++;
countEl.textContent = `${currCount}/10`;
}
const btns = document.querySelectorAll(".emoji-btn");
--fcc-editable-region--
const happyBtn = document.querySelector("#happy-btn");
const confusedBtn = document.querySelector("#confused-btn");
const sadBtn = document.querySelector("#sad-btn");
const lovingBtn = document.querySelector("#loving-btn");
happyBtn.addEventListener("click", () => updateCount(happyBtn));
confusedBtn.addEventListener("click", () => updateCount(confusedBtn));
sadBtn.addEventListener("click", () => updateCount(sadBtn));
lovingBtn.addEventListener("click", () => updateCount(lovingBtn));
--fcc-editable-region--
```

View File

@@ -0,0 +1,72 @@
{
"name": "Build an Emoji Reactor",
"blockType": "workshop",
"blockLayout": "challenge-grid",
"isUpcomingChange": false,
"dashedName": "workshop-emoji-reactor",
"helpCategory": "JavaScript",
"challengeOrder": [
{
"id": "688c90634eb5ae69845ac35d",
"title": "Step 1"
},
{
"id": "6899b0d1825ff24e9fe8d747",
"title": "Step 2"
},
{
"id": "6899b1d3bb656e56bd6937e2",
"title": "Step 3"
},
{
"id": "6899b593d232e07617f74055",
"title": "Step 4"
},
{
"id": "6899b7755876b10444ae3bcd",
"title": "Step 5"
},
{
"id": "6899b84e392df30ae370985e",
"title": "Step 6"
},
{
"id": "6899c30b1d26094e11170c92",
"title": "Step 7"
},
{
"id": "689af0bf1c707336ee9a1842",
"title": "Step 8"
},
{
"id": "689b15aacce1ae176ec768dc",
"title": "Step 9"
},
{
"id": "689b17e7e63b8e2c13839e98",
"title": "Step 10"
},
{
"id": "68a9f8378ddba1261a268cce",
"title": "Step 11"
},
{
"id": "68a9fa161498c3324ac06fe1",
"title": "Step 12"
},
{
"id": "68a9fa1787009f3293b7ba7f",
"title": "Step 13"
},
{
"id": "68a9fa1976616e330813a96c",
"title": "Step 14"
},
{
"id": "68a9fa18ad7a8432d0fc8621",
"title": "Step 15"
}
],
"usesMultifileEditor": true,
"hasEditableBoundaries": true
}

View File

@@ -421,6 +421,7 @@
"blocks": [
"lecture-working-with-the-dom-click-events-and-web-apis",
"workshop-storytelling-app",
"workshop-emoji-reactor",
"lab-favorite-icon-toggler",
"lecture-understanding-the-event-object-and-event-delegation",
"workshop-music-instrument-filter",