diff --git a/curriculum/challenges/_meta/learn-form-validation-by-building-a-calorie-counter/meta.json b/curriculum/challenges/_meta/learn-form-validation-by-building-a-calorie-counter/meta.json
index 70f761b7c58..21b5f162b4f 100644
--- a/curriculum/challenges/_meta/learn-form-validation-by-building-a-calorie-counter/meta.json
+++ b/curriculum/challenges/_meta/learn-form-validation-by-building-a-calorie-counter/meta.json
@@ -15,303 +15,376 @@
"Step 1"
],
[
- "5ddb965c65d27e1512d44d9b",
+ "63b606f09a14cc1781aea1fb",
"Step 2"
],
[
- "5ddb965c65d27e1512d44d9c",
+ "63b6075a62883218d282504c",
"Step 3"
],
[
- "5ddb965c65d27e1512d44d9d",
+ "63b607af6fcdb119aae9b16a",
"Step 4"
],
[
- "5ddb965c65d27e1512d44d9e",
+ "63b60821c855d01b1eda3c0b",
"Step 5"
],
[
- "5ddb965c65d27e1512d44d9f",
+ "63b6088bb56e2d1cac364043",
"Step 6"
],
[
- "5ddb965c65d27e1512d44da0",
+ "63b608ebf40c871d960fc004",
"Step 7"
],
[
- "5ddb965c65d27e1512d44da1",
+ "63b60a140bf5a321d50a7315",
"Step 8"
],
[
- "5ddb965c65d27e1512d44da2",
+ "63b60aaaa65f8922bfce6b7e",
"Step 9"
],
[
- "5ddb965c65d27e1512d44da3",
+ "63b60af1a0b9f7238a9dd294",
"Step 10"
],
[
- "5ddb965c65d27e1512d44da4",
+ "63b60c09c5039f25a3b2dda9",
"Step 11"
],
[
- "5ddb965c65d27e1512d44da5",
+ "63b60ca38c897f2721b27959",
"Step 12"
],
[
- "5ddb965c65d27e1512d44da6",
+ "63b60cfaca25bb27edd40f62",
"Step 13"
],
[
- "5ddb965c65d27e1512d44da7",
+ "63b60d3c5048302906962231",
"Step 14"
],
[
- "5ddb965c65d27e1512d44da8",
+ "63b613f367584d2a5d041b7d",
"Step 15"
],
[
- "5ddb965c65d27e1512d44da9",
+ "63b61490e633a22b4593e62f",
"Step 16"
],
[
- "5ddb965c65d27e1512d44daa",
+ "63b614e6a1f7fe2cef6312dc",
"Step 17"
],
[
- "5ddb965c65d27e1512d44dab",
+ "63b6152e6aff882db819fc1e",
"Step 18"
],
[
- "5ddb965c65d27e1512d44dac",
+ "63b61584def8fa2ebcc259e0",
"Step 19"
],
[
- "5ddb965c65d27e1512d44dad",
+ "63bf43be3f969d24d4ed233c",
"Step 20"
],
[
- "5e302e80e003129199103c78",
+ "63bf446945d34d25e6db6e4f",
"Step 21"
],
[
- "5e302e8ce003129199103c79",
+ "63bf45ce0dc8d4270760c6d0",
"Step 22"
],
[
- "5ddb965c65d27e1512d44dae",
+ "63bf461011fca327d3b60fa8",
"Step 23"
],
[
- "5ddb965c65d27e1512d44daf",
+ "63bf47fd40599f29827f484d",
"Step 24"
],
[
- "5ddb965c65d27e1512d44db0",
+ "63bf492b6dfb292a79f0e675",
"Step 25"
],
[
- "5ddb965c65d27e1512d44db1",
+ "63bf4bfe9de3852be51c8f86",
"Step 26"
],
[
- "5ddb965c65d27e1512d44db2",
+ "63bf4d351e06432ce9bf3627",
"Step 27"
],
[
- "5ddb965c65d27e1512d44db3",
+ "63bf511b85b6082e54dc1573",
"Step 28"
],
[
- "5ddb965c65d27e1512d44db4",
+ "63bf5230bccd1c2f5c13e1ce",
"Step 29"
],
[
- "5ddb965c65d27e1512d44db5",
+ "63bf598a4c807930a13a1a27",
"Step 30"
],
[
- "5ddb965c65d27e1512d44db6",
+ "63bf5a518d54f63181ab639a",
"Step 31"
],
[
- "5ddb965c65d27e1512d44db7",
+ "63bf5a92fd148d3264d5322b",
"Step 32"
],
[
- "5ddb965c65d27e1512d44db8",
+ "63bf5adfe2981b332eb007b6",
"Step 33"
],
[
- "5ddb965c65d27e1512d44db9",
+ "63bf5bcfebff0734593fad19",
"Step 34"
],
[
- "5ddb965c65d27e1512d44dba",
+ "63bf5c438f523a359769106c",
"Step 35"
],
[
- "5ddb965c65d27e1512d44dbb",
+ "63bf5cf03b50bf36cfbe94ea",
"Step 36"
],
[
- "5ddb965c65d27e1512d44dbc",
+ "63c1dfbd56c71e278800010c",
"Step 37"
],
[
- "5ddb965c65d27e1512d44dbd",
+ "63c1e0af28078f2dfad9eb3e",
"Step 38"
],
[
- "5ddb965c65d27e1512d44dbe",
+ "63c1e1965a898d302e0af4e3",
"Step 39"
],
[
- "5ddb965c65d27e1512d44dbf",
+ "63c1e5b4b3c8a031def3bd65",
"Step 40"
],
[
- "5ddb965c65d27e1512d44dc0",
+ "63c1e704ee12703347625900",
"Step 41"
],
[
- "5ddb965c65d27e1512d44dc1",
+ "63c2164c0df38a382062c4af",
"Step 42"
],
[
- "5ddb965c65d27e1512d44dc2",
+ "63c216da562fbb3957b9cb2c",
"Step 43"
],
[
- "5ddb965c65d27e1512d44dc3",
+ "63c2171c1e5b6e3aa51768d0",
"Step 44"
],
[
- "5ddb965c65d27e1512d44dc4",
+ "63c21774193de43bbc6a769f",
"Step 45"
],
[
- "5ddb965c65d27e1512d44dc5",
+ "63c217ccd939053ce4fa16d6",
"Step 46"
],
[
- "5ddb965c65d27e1512d44dc6",
+ "63c21839f56eaf3ef4e027c4",
"Step 47"
],
[
- "5ddb965c65d27e1512d44dc7",
+ "63c2187f55eb0f400269568f",
"Step 48"
],
[
- "5ddb965c65d27e1512d44dc8",
+ "63c218c028c56a411b2a379a",
"Step 49"
],
[
- "5ddb965c65d27e1512d44dc9",
+ "63c21dea919c8e4adb0df8e8",
"Step 50"
],
[
- "5ddb965c65d27e1512d44dca",
+ "63c2194dce265f429300c8b1",
"Step 51"
],
[
- "5ddb965c65d27e1512d44dcb",
+ "63c21c17fa8fd6447ff0389d",
"Step 52"
],
[
- "5ddb965c65d27e1512d44dcc",
+ "63c21cd2c34541469f5700a9",
"Step 53"
],
[
- "5ddb965c65d27e1512d44dcd",
+ "63c21d4f48267a47c2946788",
"Step 54"
],
[
- "5ddb965c65d27e1512d44dce",
+ "63c8ab51214c8c1f1b9a49f7",
"Step 55"
],
[
- "5ddb965c65d27e1512d44dcf",
+ "63c8ad0cd8f1e5201c4ef2e4",
"Step 56"
],
[
- "5ddb965c65d27e1512d44dd0",
+ "63c8b0187cceff21c8389543",
"Step 57"
],
[
- "5ddb965c65d27e1512d44dd1",
+ "63c8be904ffff922f3c6f8d0",
"Step 58"
],
[
- "5ddb965c65d27e1512d44dd2",
+ "63c8c00bfb671b23f9de4159",
"Step 59"
],
[
- "5ddb965c65d27e1512d44dd3",
+ "63c8c15fd337ad24b9b68049",
"Step 60"
],
[
- "5ddb965c65d27e1512d44dd4",
+ "63c9bc53735149084390e5d0",
"Step 61"
],
[
- "5ddb965c65d27e1512d44dd5",
+ "63c9bcc26219e7090da0f549",
"Step 62"
],
[
- "5ddb965c65d27e1512d44dd6",
+ "63c9bce376ca4f09c15a3768",
"Step 63"
],
[
- "5ddb965c65d27e1512d44dd7",
+ "63c9bdd916e0c10af01ed8d7",
"Step 64"
],
[
- "5ddb965c65d27e1512d44dd8",
+ "63c9be334f4a050c0b94bc93",
"Step 65"
],
[
- "5ddb965c65d27e1512d44dd9",
+ "63c9bef7fec05c0d38853828",
"Step 66"
],
[
- "5ddb965c65d27e1512d44dda",
+ "63c9bf80558d780e848b2987",
"Step 67"
],
[
- "5ddb965c65d27e1512d44ddb",
+ "63c9c09a7daa4f0ff92c4023",
"Step 68"
],
[
- "5ddb965c65d27e1512d44ddc",
+ "63c9c0d0857f0a10a57af936",
"Step 69"
],
[
- "5ddb965c65d27e1512d44ddd",
+ "63c9c11a0a090311dff55564",
"Step 70"
],
[
- "5ddb965c65d27e1512d44dde",
+ "63c9c16dd75dd212dc12363c",
"Step 71"
],
[
- "5ddb965c65d27e1512d44ddf",
+ "63c9c1ef134f3513e751c975",
"Step 72"
],
[
- "5ddb965c65d27e1512d44de0",
+ "63c9e3a83bb3e61a80eea564",
"Step 73"
],
[
- "5ddb965c65d27e1512d44de1",
+ "63c9e45519caf31b987fbb5f",
"Step 74"
],
[
- "5ddb965c65d27e1512d44de2",
+ "63c9e4d2ff41811dd640504f",
"Step 75"
],
[
- "5ddb965c65d27e1512d44de3",
+ "63c9e51b3a007a1eba1cd0f6",
"Step 76"
+ ],
+ [
+ "63c9e55b4b06c11fff555c64",
+ "Step 77"
+ ],
+ [
+ "63c9e5eea8261d22856ead1c",
+ "Step 78"
+ ],
+ [
+ "63c9e63bb1e32d23b6adbe44",
+ "Step 79"
+ ],
+ [
+ "63c9e6b7c0303524af2d0bc2",
+ "Step 80"
+ ],
+ [
+ "63c9e769df38c92635c158ba",
+ "Step 81"
+ ],
+ [
+ "63c9e7d5b21eee2776ecc226",
+ "Step 82"
+ ],
+ [
+ "63c9e84c9fe8ca28c4101189",
+ "Step 83"
+ ],
+ [
+ "63c9e8fe3a6f022a05a04675",
+ "Step 84"
+ ],
+ [
+ "63c9e94e9df7d72aed1c24bd",
+ "Step 85"
+ ],
+ [
+ "63c9ea23dbadbf2c2764e3f5",
+ "Step 86"
+ ],
+ [
+ "63c9ea9b16430f2d54522464",
+ "Step 87"
+ ],
+ [
+ "63c9eb09bcfaa72e3da820a1",
+ "Step 88"
+ ],
+ [
+ "63c9eb4a5d68f12f32d9b440",
+ "Step 89"
+ ],
+ [
+ "63c9ebb7b12bca3025b0a935",
+ "Step 90"
+ ],
+ [
+ "63c9ec044acedf312c4974ff",
+ "Step 91"
+ ],
+ [
+ "63c9f24afbc9cf324dcaa9a4",
+ "Step 92"
+ ],
+ [
+ "63c9f28bda3e3f336e21b6b4",
+ "Step 93"
+ ],
+ [
+ "63c9f2bff625af342023512c",
+ "Step 94"
]
- ]}
+ ]
+}
\ No newline at end of file
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/5ddb965c65d27e1512d44d9a.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/5ddb965c65d27e1512d44d9a.md
new file mode 100644
index 00000000000..c3def32154d
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/5ddb965c65d27e1512d44d9a.md
@@ -0,0 +1,122 @@
+---
+id: 5ddb965c65d27e1512d44d9a
+title: Step 1
+challengeType: 0
+dashedName: step-1
+---
+
+# --description--
+
+You have been provided with boilerplate CSS and HTML. However, you need to build your calorie counter form.
+
+Feel free to explore the HTML and CSS, then add a `form` element and give it an `id` set to `calorie-counter`.
+
+# --hints--
+
+You should have a `form` element.
+
+```js
+assert.exists(document.querySelector('form'));
+```
+
+Your `form` element should have an `id` attribute set to `calorie-counter`.
+
+```js
+assert.equal(document.querySelector('form')?.id, 'calorie-counter');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b606f09a14cc1781aea1fb.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b606f09a14cc1781aea1fb.md
new file mode 100644
index 00000000000..e938bc8c2e3
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b606f09a14cc1781aea1fb.md
@@ -0,0 +1,146 @@
+---
+id: 63b606f09a14cc1781aea1fb
+title: Step 2
+challengeType: 0
+dashedName: step-2
+---
+
+# --description--
+
+Create a `label` element, give it a `for` attribute set to `budget` and the text `Budget`, then create an `input` element with the `id` set to `budget`.
+
+# --hints--
+
+You should create a `label` element in your `form`.
+
+```js
+assert.exists(document.querySelector('form label'));
+```
+
+Your `label` element should have a `for` attribute set to `budget`.
+
+```js
+assert.equal(document.querySelector('form label')?.getAttribute('for'), 'budget');
+```
+
+Your `label` element should have the text `Budget`.
+
+```js
+assert.equal(document.querySelector('form label')?.innerText, 'Budget');
+```
+
+You should create an `input` element within your `form`.
+
+```js
+assert.exists(document.querySelector('form input'));
+```
+
+Your `input` element should come after your `label` element.
+
+```js
+assert.equal(document.querySelector('form input')?.previousElementSibling?.tagName, "LABEL");
+```
+
+Your `input` element should have an `id` set to `budget`.
+
+```js
+assert.equal(document.querySelector('form input')?.id, "budget");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b6075a62883218d282504c.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b6075a62883218d282504c.md
new file mode 100644
index 00000000000..fcabad47a30
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b6075a62883218d282504c.md
@@ -0,0 +1,131 @@
+---
+id: 63b6075a62883218d282504c
+title: Step 3
+challengeType: 0
+dashedName: step-3
+---
+
+# --description--
+
+Your `input` element needs some additional attributes. Give it a `type` set to `number` to only allow numeric inputs, a `min` attribute set to `0` to only allow positive numbers, and a `placeholder` set to `Daily calorie budget`.
+
+Finally, mark the `input` element as `required`.
+
+# --hints--
+
+Your `input` element should have a `type` attribute set to `number`.
+
+```js
+assert.equal(document.querySelector('form input').type, 'number');
+```
+
+Your `input` element should have a `min` attribute set to `0`.
+
+```js
+assert.equal(document.querySelector('form input').min, '0');
+```
+
+Your `input` element should have a `placeholder` attribute set to `Daily calorie budget`.
+
+```js
+assert.equal(document.querySelector('form input').placeholder, 'Daily calorie budget');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b607af6fcdb119aae9b16a.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b607af6fcdb119aae9b16a.md
new file mode 100644
index 00000000000..5079bde79a8
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b607af6fcdb119aae9b16a.md
@@ -0,0 +1,168 @@
+---
+id: 63b607af6fcdb119aae9b16a
+title: Step 4
+challengeType: 0
+dashedName: step-4
+---
+
+# --description--
+
+Create a `fieldset` element with the `id` set to `breakfast`.
+
+Within that element, create a `legend` with the text `Breakfast`, and an empty `div` with the `class` set to `input-container`.
+
+# --hints--
+
+You should create a `fieldset` element in your `form`.
+
+```js
+assert.exists(document.querySelector('form fieldset'));
+```
+
+Your `fieldset` element should come after your `input` element.
+
+```js
+assert.equal(document.querySelector('form fieldset')?.previousElementSibling?.tagName, "INPUT");
+```
+
+Your `fieldset` element should have an `id` set to `breakfast`.
+
+```js
+assert.equal(document.querySelector('form fieldset')?.id, "breakfast");
+```
+
+You should create a `legend` element within your `fieldset`.
+
+```js
+assert.exists(document.querySelector('form fieldset legend'));
+```
+
+Your `legend` element should have the text `Breakfast`.
+
+```js
+assert.equal(document.querySelector('form fieldset legend')?.innerText, "Breakfast");
+```
+
+You should create a `div` element within your `fieldset`.
+
+```js
+assert.exists(document.querySelector('form fieldset div'));
+```
+
+Your `div` element should come after your `legend` element.
+
+```js
+assert.equal(document.querySelector('form fieldset div')?.previousElementSibling?.tagName, "LEGEND");
+```
+
+Your `div` element should have a `class` set to `input-container`.
+
+```js
+assert.equal(document.querySelector('form fieldset div')?.className, "input-container");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60821c855d01b1eda3c0b.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60821c855d01b1eda3c0b.md
new file mode 100644
index 00000000000..7de68f5215c
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60821c855d01b1eda3c0b.md
@@ -0,0 +1,164 @@
+---
+id: 63b60821c855d01b1eda3c0b
+title: Step 5
+challengeType: 0
+dashedName: step-5
+---
+
+# --description--
+
+Now create a `fieldset` with an `id` set to `lunch`, and a corresponding `legend` and `div` element.
+
+# --hints--
+
+You should create a second `fieldset` element in your `form`.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[1]);
+```
+
+Your second `fieldset` element should come after your first `fieldset` element.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[1]?.previousElementSibling?.tagName, "FIELDSET");
+```
+
+Your second `fieldset` element should have an `id` set to `lunch`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[1]?.id, "lunch");
+```
+
+Your second `fieldset` element should contain a `legend` element.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[1]?.querySelector('legend'));
+```
+
+Your new `legend` element should have the text `Lunch`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[1]?.querySelector('legend')?.innerText, "Lunch");
+```
+
+Your second `fieldset` element should contain a `div` element.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[1]?.querySelector('div'));
+```
+
+Your new `div` element should have a `class` set to `input-container`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[1]?.querySelector('div')?.className, "input-container");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b6088bb56e2d1cac364043.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b6088bb56e2d1cac364043.md
new file mode 100644
index 00000000000..f7c617f998e
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b6088bb56e2d1cac364043.md
@@ -0,0 +1,168 @@
+---
+id: 63b6088bb56e2d1cac364043
+title: Step 6
+challengeType: 0
+dashedName: step-6
+---
+
+# --description--
+
+Continuing the pattern, create a `fieldset` for `dinner` with the same nested elements.
+
+# --hints--
+
+You should create a third `fieldset` element in your `form`.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[2]);
+```
+
+Your third `fieldset` element should come after your second `fieldset` element.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[2]?.previousElementSibling?.tagName, "FIELDSET");
+```
+
+Your third `fieldset` element should have an `id` set to `dinner`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[2]?.id, "dinner");
+```
+
+Your third `fieldset` element should contain a `legend` element.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[2]?.querySelector('legend'));
+```
+
+Your new `legend` element should have the text `Dinner`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[2]?.querySelector('legend')?.innerText, "Dinner");
+```
+
+Your third `fieldset` element should contain a `div` element.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[2]?.querySelector('div'));
+```
+
+Your new `div` element should have a `class` set to `input-container`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[2]?.querySelector('div')?.className, "input-container");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b608ebf40c871d960fc004.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b608ebf40c871d960fc004.md
new file mode 100644
index 00000000000..911126b33e4
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b608ebf40c871d960fc004.md
@@ -0,0 +1,214 @@
+---
+id: 63b608ebf40c871d960fc004
+title: Step 7
+challengeType: 0
+dashedName: step-7
+---
+
+# --description--
+
+You need two more of these `fieldset` code blocks – one for `snacks` and one for `exercise`.
+
+# --hints--
+
+You should create a fourth `fieldset` element in your `form`.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[3]);
+```
+
+Your fourth `fieldset` element should come after your third `fieldset` element.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[3]?.previousElementSibling?.tagName, "FIELDSET");
+```
+
+Your fourth `fieldset` element should have an `id` set to `snacks`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[3]?.id, "snacks");
+```
+
+Your fourth `fieldset` element should contain a `legend` element.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[3]?.querySelector('legend'));
+```
+
+Your fourth `legend` element should have the text `Snacks`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[3]?.querySelector('legend')?.innerText, "Snacks");
+```
+
+Your fourth `fieldset` element should contain a `div` element.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[3]?.querySelector('div'));
+```
+
+Your fifth `div` element should have a `class` set to `input-container`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[3]?.querySelector('div')?.className, "input-container");
+```
+
+You should create a fifth `fieldset` element in your `form`.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[4]);
+```
+
+Your fifth `fieldset` element should come after your fourth `fieldset` element.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[4]?.previousElementSibling?.tagName, "FIELDSET");
+```
+
+Your fifth `fieldset` element should have an `id` set to `exercise`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[4]?.id, "exercise");
+```
+
+Your fifth `fieldset` element should contain a `legend` element.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[4]?.querySelector('legend'));
+```
+
+Your fifth `legend` element should have the text `Exercise`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[4]?.querySelector('legend')?.innerText, "Exercise");
+```
+
+Your fifth `fieldset` element should contain a `div` element.
+
+```js
+assert.exists(document.querySelectorAll('form fieldset')[4]?.querySelector('div'));
+```
+
+Your fifth `div` element should have a `class` set to `input-container`.
+
+```js
+assert.equal(document.querySelectorAll('form fieldset')[4]?.querySelector('div')?.className, "input-container");
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60a140bf5a321d50a7315.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60a140bf5a321d50a7315.md
new file mode 100644
index 00000000000..068bea72dfc
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60a140bf5a321d50a7315.md
@@ -0,0 +1,163 @@
+---
+id: 63b60a140bf5a321d50a7315
+title: Step 8
+challengeType: 0
+dashedName: step-8
+---
+
+# --description--
+
+Create a `div` and give it a `class` set to `controls`. Nest a `span` element within that `div`.
+
+# --hints--
+
+You should create a new `div` element in your `form`.
+
+```js
+assert.exists(document.querySelector('form > div'));
+```
+
+Your `div` element should come after your `fieldset` elements.
+
+```js
+assert.equal(document.querySelector('form > div')?.previousElementSibling?.tagName, "FIELDSET");
+assert.notExists(document.querySelector('form > div')?.nextElementSibling);
+```
+
+Your `div` element should have a `class` attribute set to `controls`.
+
+```js
+assert.equal(document.querySelector('form > div')?.className, "controls");
+```
+
+You should nest a `span` element within your `div`.
+
+```js
+assert.exists(document.querySelector('form > div > span'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60aaaa65f8922bfce6b7e.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60aaaa65f8922bfce6b7e.md
new file mode 100644
index 00000000000..c9723d26fcb
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60aaaa65f8922bfce6b7e.md
@@ -0,0 +1,210 @@
+---
+id: 63b60aaaa65f8922bfce6b7e
+title: Step 9
+challengeType: 0
+dashedName: step-9
+---
+
+# --description--
+
+In your `span` element, create a `label` element for an `entry-dropdown` and give it the text `Add food or exercise:`. Then create a `select` element with the `id` set to `entry-dropdown` and a `name` set to `options`. Below that, add a `button` element with the `id` set to `add-entry` and the text `Add Entry`.
+
+Give your `button` element a `type` attribute set to `button` to prevent automatic form submission.
+
+# --hints--
+
+You should add a `label` element to your `span` element.
+
+```js
+assert.exists(document.querySelector('.controls > span > label'));
+```
+
+Your new `label` element should have a `for` attribute set to `entry-dropdown`.
+
+```js
+assert.equal(document.querySelector('.controls > span > label')?.getAttribute('for'), 'entry-dropdown');
+```
+
+Your new `label` element should have the text `Add food or exercise:`.
+
+```js
+assert.equal(document.querySelector('.controls > span > label')?.innerText, 'Add food or exercise:');
+```
+
+You should add a `select` element to your `span` element.
+
+```js
+assert.exists(document.querySelector('.controls > span > select'));
+```
+
+Your `select` element should come after your `label` element.
+
+```js
+assert(document.querySelector('.controls > span > select')?.previousElementSibling?.tagName === 'LABEL');
+```
+
+Your new `select` element should have an `id` attribute set to `entry-dropdown`.
+
+```js
+assert.equal(document.querySelector('.controls > span > select')?.getAttribute('id'), 'entry-dropdown');
+```
+
+Your new `select` element should have a `name` attribute set to `options`.
+
+```js
+assert.equal(document.querySelector('.controls > span > select')?.getAttribute('name'), 'options');
+```
+
+You should add a `button` element to your `span` element.
+
+```js
+assert.exists(document.querySelector('.controls > span > button'));
+```
+
+Your `button` element should come after your `select` element.
+
+```js
+assert(document.querySelector('.controls > span > button')?.previousElementSibling?.tagName === 'SELECT');
+```
+
+Your new `button` element should have an `id` attribute set to `add-entry`.
+
+```js
+assert.equal(document.querySelector('.controls > span > button')?.getAttribute('id'), 'add-entry');
+```
+
+Your new `button` element should have the text `Add Entry`.
+
+```js
+assert.equal(document.querySelector('.controls > span > button')?.innerText, 'Add Entry');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60af1a0b9f7238a9dd294.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60af1a0b9f7238a9dd294.md
new file mode 100644
index 00000000000..27f69a473d9
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60af1a0b9f7238a9dd294.md
@@ -0,0 +1,220 @@
+---
+id: 63b60af1a0b9f7238a9dd294
+title: Step 10
+challengeType: 0
+dashedName: step-10
+---
+
+# --description--
+
+Your select menu needs options for each of the food and exercise `fieldset` elements you created in the previous steps. Use the `option` element to create a new option for each `fieldset`. The `value` attribute of each option should be the `id` of the `fieldset`, and the text of each option should be the text of the `legend`.
+
+Set the `Breakfast` option as the `selected` option.
+
+# --hints--
+
+You should create five `option` elements within your `select` element.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.length, 5);
+```
+
+Your first `option` should have the text `Breakfast`.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.[0]?.textContent, 'Breakfast');
+```
+
+Your first `option` should have the `value` attribute set to `breakfast`.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.[0]?.value, 'breakfast');
+```
+
+Your second `option` should have the text `Lunch`.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.[1]?.textContent, 'Lunch');
+```
+
+Your second `option` should have the `value` attribute set to `lunch`.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.[1]?.value, 'lunch');
+```
+
+Your third `option` should have the text `Dinner`.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.[2]?.textContent, 'Dinner');
+```
+
+Your third `option` should have the `value` attribute set to `dinner`.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.[2]?.value, 'dinner');
+```
+
+Your fourth `option` should have the text `Snacks`.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.[3]?.textContent, 'Snacks');
+```
+
+Your fourth `option` should have the `value` attribute set to `snacks`.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.[3]?.value, 'snacks');
+```
+
+Your fifth `option` should have the text `Exercise`.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.[4]?.textContent, 'Exercise');
+```
+
+Your fifth `option` should have the `value` attribute set to `exercise`.
+
+```js
+assert.equal(document.querySelectorAll('.controls select option')?.[4]?.value, 'exercise');
+```
+
+Your first `option` should be selected by default.
+
+```js
+assert.isTrue(document.querySelectorAll('.controls select option')?.[0]?.getAttributeNames()?.includes('selected'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60c09c5039f25a3b2dda9.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60c09c5039f25a3b2dda9.md
new file mode 100644
index 00000000000..4e28d650816
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60c09c5039f25a3b2dda9.md
@@ -0,0 +1,207 @@
+---
+id: 63b60c09c5039f25a3b2dda9
+title: Step 11
+challengeType: 0
+dashedName: step-11
+---
+
+# --description--
+
+Create another `div` element. Within it, nest a `button` to `submit` the form, with an `id` set to `calculate-calories`. This button should have the text `Calculate Remaining Calories`.
+
+Then add a `button` with the `id` set to `clear` to clear the form (don't forget to give it a `type` attribute that prevents it from submitting the form). This button needs the text `Clear`.
+
+# --hints--
+
+You should create a second `div` element.
+
+```js
+assert.equal(document.querySelectorAll('form > div')?.length, 2);
+```
+
+Your new `div` element should have a `button` element.
+
+```js
+assert.exists(document.querySelectorAll('form > div')?.[1]?.querySelector('button'));
+```
+
+Your `button` element should have a `type` attribute set to `submit`.
+
+```js
+assert.equal(document.querySelectorAll('form > div')?.[1]?.querySelector('button')?.getAttribute('type'), 'submit');
+```
+
+Your `button` element should have an `id` attribute set to `calculate-calories`.
+
+```js
+assert.equal(document.querySelectorAll('form > div')?.[1]?.querySelector('button')?.getAttribute('id'), 'calculate-calories');
+```
+
+Your `button` element should have the text `Calculate Remaining Calories`.
+
+```js
+assert.equal(document.querySelectorAll('form > div')?.[1]?.querySelector('button')?.innerText, 'Calculate Remaining Calories');
+```
+
+Your `div` element should have a second `button` element.
+
+```js
+assert.exists(document.querySelectorAll('form > div')?.[1]?.querySelectorAll('button')?.[1]);
+```
+
+Your second `button` element should have a `type` attribute set to `button`.
+
+```js
+assert.equal(document.querySelectorAll('form > div')?.[1]?.querySelectorAll('button')?.[1]?.getAttribute('type'), 'button');
+```
+
+Your second `button` element should have an `id` attribute set to `clear`.
+
+```js
+assert.equal(document.querySelectorAll('form > div')?.[1]?.querySelectorAll('button')?.[1]?.getAttribute('id'), 'clear');
+```
+
+Your second `button` element should have the text `Clear`.
+
+```js
+assert.equal(document.querySelectorAll('form > div')?.[1]?.querySelectorAll('button')?.[1]?.innerText, 'Clear');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60ca38c897f2721b27959.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60ca38c897f2721b27959.md
new file mode 100644
index 00000000000..aaf24c8d8cb
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60ca38c897f2721b27959.md
@@ -0,0 +1,182 @@
+---
+id: 63b60ca38c897f2721b27959
+title: Step 12
+challengeType: 0
+dashedName: step-12
+---
+
+# --description--
+
+Your form needs somewhere to display the results. Add an empty `div` element and give it an `id` of `output` and the `class` values of `output` and `hide`.
+
+# --hints--
+
+You should add a `div` element after your `form`.
+
+```js
+assert.exists(document.querySelector('.container > div'));
+```
+
+Your new `div` element should have an `id` set to `output`.
+
+```js
+assert.equal(document.querySelector('.container > div')?.id, 'output');
+```
+
+Your new `div` element should have the `class` values of `output` and `hide`.
+
+```js
+assert.include(document.querySelector('.container > div')?.className.split(/\s+/), 'output');
+assert.include(document.querySelector('.container > div')?.className.split(/\s+/), 'hide');
+```
+
+Your new `div` should be empty.
+
+```js
+assert.equal(document.querySelector('.container > div')?.innerHTML, '');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60cfaca25bb27edd40f62.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60cfaca25bb27edd40f62.md
new file mode 100644
index 00000000000..17934b0039d
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60cfaca25bb27edd40f62.md
@@ -0,0 +1,170 @@
+---
+id: 63b60cfaca25bb27edd40f62
+title: Step 13
+challengeType: 0
+dashedName: step-13
+---
+
+# --description--
+
+Finally, you need to link your JavaScript file to your HTML. Create a `script` element to do so.
+
+# --hints--
+
+You should have a `script` element.
+
+```js
+assert.isAtLeast(document.querySelectorAll('script')?.length, 1);
+```
+
+Your `script` element should have the `src` set to `./script.js`.
+
+```js
+assert.match(code, /script\s*?src\s*?=\s*?('|")(\.\/)?script\.js\1/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60d3c5048302906962231.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60d3c5048302906962231.md
new file mode 100644
index 00000000000..de3870b44ad
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b60d3c5048302906962231.md
@@ -0,0 +1,176 @@
+---
+id: 63b60d3c5048302906962231
+title: Step 14
+challengeType: 0
+dashedName: step-14
+---
+
+# --description--
+
+It is time to start writing the script that makes your form work. Begin by getting the `form` element (using the `id`) and storing it in a variable called `calorieCounter`.
+
+# --hints--
+
+You should create a variable called `calorieCounter`.
+
+```js
+assert.isDefined(calorieCounter);
+```
+
+You should use `document.getElementById()` to get the `#calorie-counter` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|")calorie-counter\1\s*\)/g);
+```
+
+You should store the `#calorie-counter` element in a variable called `calorieCounter`.
+
+```js
+assert.equal(calorieCounter, document.getElementById('calorie-counter'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b613f367584d2a5d041b7d.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b613f367584d2a5d041b7d.md
new file mode 100644
index 00000000000..44e1c274573
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b613f367584d2a5d041b7d.md
@@ -0,0 +1,195 @@
+---
+id: 63b613f367584d2a5d041b7d
+title: Step 15
+challengeType: 0
+dashedName: step-15
+---
+
+# --description--
+
+Get your `#budget` element and assign it to `budgetNumberInput`, and your `#entry-dropdown` element and assign it to `entryDropdown`.
+
+# --hints--
+
+You should declare a variable called `budgetNumberInput`.
+
+```js
+assert.isDefined(budgetNumberInput);
+```
+
+You should use `document.getElementById()` to get the `#budget` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|")budget\1\s*\)/g);
+```
+
+You should store the `#budget` element in a variable called `budgetNumberInput`.
+
+```js
+assert.equal(budgetNumberInput, document.getElementById('budget'));
+```
+
+You should declare a variable called `entryDropdown`.
+
+```js
+assert.isDefined(entryDropdown);
+```
+
+You should use `document.getElementById()` to get the `#entry-dropdown` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|")entry-dropdown\1\s*\)/g);
+```
+
+You should store the `#entry-dropdown` element in a variable called `entryDropdown`.
+
+```js
+assert.equal(entryDropdown, document.getElementById('entry-dropdown'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+--fcc-editable-region--
+const calorieCounter = document.getElementById('calorie-counter');
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b61490e633a22b4593e62f.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b61490e633a22b4593e62f.md
new file mode 100644
index 00000000000..6cbbeb5ab4a
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b61490e633a22b4593e62f.md
@@ -0,0 +1,215 @@
+---
+id: 63b61490e633a22b4593e62f
+title: Step 16
+challengeType: 0
+dashedName: step-16
+---
+
+# --description--
+
+Following the same pattern, assign your `#add-entry` element to `addEntryButton`, your `#clear` element to `clearButton`, and your `#output` element to `output`.
+
+# --hints--
+
+You should declare a variable called `addEntryButton`.
+
+```js
+assert.isDefined(addEntryButton);
+```
+
+You should use `document.getElementById()` to get the `#add-entry` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|")add-entry\1\s*\)/g);
+```
+
+You should assign the `#add-entry` element to `addEntryButton`.
+
+```js
+assert.equal(addEntryButton, document.getElementById('add-entry'));
+```
+
+You should declare a variable called `clearButton`.
+
+```js
+assert.isDefined(clearButton);
+```
+
+You should use `document.getElementById()` to get the `#clear` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|")clear\1\s*\)/g);
+```
+
+You should assign the `#clear` element to `clearButton`.
+
+```js
+assert.equal(clearButton, document.getElementById('clear'));
+```
+
+You should declare a variable called `output`.
+
+```js
+assert.isDefined(output);
+```
+
+You should use `document.getElementById()` to get the `#output` element.
+
+```js
+assert.match(code, /document\.getElementById\(\s*('|")output\1\s*\)/g);
+```
+
+You should assign the `#output` element to `output`.
+
+```js
+assert.equal(output, document.getElementById("output"));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+--fcc-editable-region--
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b614e6a1f7fe2cef6312dc.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b614e6a1f7fe2cef6312dc.md
new file mode 100644
index 00000000000..99c1985862c
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b614e6a1f7fe2cef6312dc.md
@@ -0,0 +1,182 @@
+---
+id: 63b614e6a1f7fe2cef6312dc
+title: Step 17
+challengeType: 0
+dashedName: step-17
+---
+
+# --description--
+
+Declare an `isError` variable and set it to `false`, but use `let` so you can reassign it later.
+
+# --hints--
+
+You should declare an `isError` variable.
+
+```js
+assert.isDefined(isError);
+```
+
+Your `isError` variable should be set to `false`.
+
+```js
+assert.isFalse(isError);
+```
+
+You should use `let` to declare your `isError` variable.
+
+```js
+assert.match(code, /let\s+isError\s*=\s*false/g);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+--fcc-editable-region--
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b6152e6aff882db819fc1e.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b6152e6aff882db819fc1e.md
new file mode 100644
index 00000000000..436b65b80d6
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b6152e6aff882db819fc1e.md
@@ -0,0 +1,192 @@
+---
+id: 63b6152e6aff882db819fc1e
+title: Step 18
+challengeType: 0
+dashedName: step-18
+---
+
+# --description--
+
+Even though you set an `input` element to be a number, JavaScript receives a string value. You need to write a function to clean the string value and ensure you have a number.
+
+Start by declaring a `cleanInputString` function that takes a `str` argument.
+
+# --hints--
+
+You should declare a `cleanInputString` variable.
+
+```js
+assert.isDefined(cleanInputString);
+```
+
+Your `cleanInputString` variable should be a function.
+
+```js
+assert.isFunction(cleanInputString);
+```
+
+Your `cleanInputString` function should take a `str` argument.
+
+```js
+assert.match(cleanInputString?.toString(), /\(str\)/);
+```
+
+`cleanInputString` should be an empty function.
+
+```js
+assert.match(cleanInputString?.toString(), /\{\s*\}/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b61584def8fa2ebcc259e0.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b61584def8fa2ebcc259e0.md
new file mode 100644
index 00000000000..f80fb3fdf2e
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63b61584def8fa2ebcc259e0.md
@@ -0,0 +1,182 @@
+---
+id: 63b61584def8fa2ebcc259e0
+title: Step 19
+challengeType: 0
+dashedName: step-19
+---
+
+# --description--
+
+You need to split your `str` into individual characters. Remember that strings have a `.split()` method, and if you pass an empty string it will split on every character.
+
+Declare a `strArray` variable and assign it that split value.
+
+# --hints--
+
+Your `cleanInputString` function should declare a `strArray` variable.
+
+```js
+assert.match(cleanInputString.toString(), /strArray\s*=/);
+```
+
+Your `strArray` variable should be assigned the value of `str.split('')`.
+
+```js
+assert.match(cleanInputString.toString(), /strArray\s*=\s*str\.split\(\s*('|")\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+function cleanInputString(str) {
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf43be3f969d24d4ed233c.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf43be3f969d24d4ed233c.md
new file mode 100644
index 00000000000..6f74ea42501
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf43be3f969d24d4ed233c.md
@@ -0,0 +1,181 @@
+---
+id: 63bf43be3f969d24d4ed233c
+title: Step 20
+challengeType: 0
+dashedName: step-20
+---
+
+# --description--
+
+Declare a `cleanStrArray` variable and assign it an empty array. You will use this to store your valid number characters.
+
+# --hints--
+
+Your `cleanInputString` should declare a variable called `cleanStrArray`.
+
+```js
+assert.match(cleanInputString.toString(), /cleanStrArray\s*/g);
+```
+
+Your `cleanStrArray` variable should be assigned an empty array.
+
+```js
+assert.match(cleanInputString.toString(), /cleanStrArray\s*=\s*\[\s*\]/g);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+function cleanInputString(str) {
+ const strArray = str.split('');
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf446945d34d25e6db6e4f.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf446945d34d25e6db6e4f.md
new file mode 100644
index 00000000000..8bf06ccc530
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf446945d34d25e6db6e4f.md
@@ -0,0 +1,195 @@
+---
+id: 63bf446945d34d25e6db6e4f
+title: Step 21
+challengeType: 0
+dashedName: step-21
+---
+
+# --description--
+
+Use a `for` loop to iterate through each character in your `strArray` array.
+
+# --hints--
+
+Your `cleanInputString` function should have a `for` loop.
+
+```js
+assert.match(cleanInputString.toString(), /for\s*\(/g);
+```
+
+Your `for` loop should initialize a variable called `i` to `0`.
+
+```js
+assert.match(cleanInputString.toString(), /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;/g);
+```
+
+Your `for` loop should have a condition that checks if `i` is less than the length of `strArray`.
+
+```js
+assert.match(cleanInputString.toString(), /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;\s*i\s*<\s*strArray\.length\s*;/g);
+```
+
+Your `for` loop should increment `i` by `1` each time it runs. Use the increment operator for this.
+
+```js
+assert.match(cleanInputString.toString(), /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;\s*i\s*<\s*strArray\.length\s*;\s*i\s*\+\+\s*\)/g);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+function cleanInputString(str) {
+ const strArray = str.split('');
+ const cleanStrArray = [];
+
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf45ce0dc8d4270760c6d0.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf45ce0dc8d4270760c6d0.md
new file mode 100644
index 00000000000..a432c6687d5
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf45ce0dc8d4270760c6d0.md
@@ -0,0 +1,200 @@
+---
+id: 63bf45ce0dc8d4270760c6d0
+title: Step 22
+challengeType: 0
+dashedName: step-22
+---
+
+# --description--
+
+Within your loop, you need to check if the character in `strArray` at index `i` is not `+`, `-`, or a space. If it is not, `push` it to the `cleanStrArray`.
+
+To check your character, see if the array `["+", "-", " "]` includes the character – you can use the `.includes()` method on the array to do this.
+
+# --hints--
+
+Your `for` loop should have an `if` statement.
+
+```js
+assert.match(cleanInputString.toString(), /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;\s*i\s*<\s*strArray\.length\s*;\s*i\s*\+\+\s*\)\s*\{\s*if\s*\(/);
+```
+
+Your `for` loop should use `!["+", "-", " "].includes()`.
+
+```js
+// the loop protection injects code so we have to look at the raw code directly
+assert.match(code, /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;\s*i\s*<\s*strArray\.length\s*;\s*i\s*\+\+\s*\)\s*\{\s*if\s*\(!\[("|')\+\2\s*,\s*("|')-\3\s*,\s*("|')\s\4\s*\]\.includes\(/);
+```
+
+Your `for` loop should see if `strArray[i]` is found in `["+", "-", " "]`.
+
+```js
+assert.match(code, /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;\s*i\s*<\s*strArray\.length\s*;\s*i\s*\+\+\s*\)\s*\{\s*if\s*\(!\[("|')\+\2\s*,\s*("|')-\3\s*,\s*("|')\s\4\s*\]\.includes\(\s*strArray\[i\]\s*\)\)\s*\{/);
+```
+
+Your `for` loop should `push` `strArray[i]` to `cleanStrArray`.
+
+```js
+assert.match(code, /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;\s*i\s*<\s*strArray\.length\s*;\s*i\s*\+\+\s*\)\s*\{\s*if\s*\(!\[("|')\+\2\s*,\s*("|')-\3\s*,\s*("|')\s\4\s*\]\.includes\(\s*strArray\[i\]\s*\)\)\s*\{\s*cleanStrArray\.push\(\s*strArray\[i\]\s*\)\s*\}/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+function cleanInputString(str) {
+ const strArray = str.split('');
+ const cleanStrArray = [];
+
+ for (let i = 0; i < strArray.length; i++) {
+
+ }
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf461011fca327d3b60fa8.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf461011fca327d3b60fa8.md
new file mode 100644
index 00000000000..f74ff636c5b
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf461011fca327d3b60fa8.md
@@ -0,0 +1,213 @@
+---
+id: 63bf461011fca327d3b60fa8
+title: Step 23
+challengeType: 0
+dashedName: step-23
+---
+
+# --description--
+
+While looping through the string works, creating a new array is inefficient for memory and runtime performance. Instead, you can use Regular Expressions (referred to as "regex") to match specific characters.
+
+Regex in JavaScript is indicated by a pattern wrapped in forward slashes – for example:
+
+```js
+const regex = /hello/;
+```
+
+Remove your existing code within the `cleanInputString` function. Declare a `regex` variable and assign it the value from the example above.
+
+# --hints--
+
+You should remove the `cleanStrArray` variable.
+
+```js
+assert.notMatch(cleanInputString.toString(), /cleanStrArray/);
+```
+
+You should remove the `strArray` variable.
+
+```js
+assert.notMatch(cleanInputString.toString(), /strArray/);
+```
+
+You should not have a `for` loop.
+
+```js
+assert.notMatch(cleanInputString.toString(), /for/);
+```
+
+You should declare a `regex` variable.
+
+```js
+assert.match(cleanInputString.toString(), /regex\s*=/);
+```
+
+Your `regex` variable should be set to the regular expression `/hello/`.
+
+```js
+assert.match(cleanInputString.toString(), /regex\s*=\s*\/hello\//);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+function cleanInputString(str) {
+ const strArray = str.split('');
+ const cleanStrArray = [];
+
+ for (let i = 0; i < strArray.length; i++) {
+ if (!["+", "-", " "].includes(strArray[i])) {
+ cleanStrArray.push(strArray[i])
+ }
+ }
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf47fd40599f29827f484d.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf47fd40599f29827f484d.md
new file mode 100644
index 00000000000..0f781eb61cf
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf47fd40599f29827f484d.md
@@ -0,0 +1,176 @@
+---
+id: 63bf47fd40599f29827f484d
+title: Step 24
+challengeType: 0
+dashedName: step-24
+---
+
+# --description--
+
+The pattern you currently have will match the exact text `hello`, which is not what you want to match. You want to look for `+`, `-`, or spaces. Replace the pattern in your `regex` variable with `\+-` to look for plus and minus characters.
+
+Note that you need to use the `\` to escape the `+`, because a `+` has a special meaning in regular expressions.
+
+# --hints--
+
+Your `regex` variable should be set to the regular expression `/\+-/`.
+
+```js
+assert.match(cleanInputString.toString(), /regex\s*=\s*\/\\\+-\//);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+function cleanInputString(str) {
+ const regex = /hello/;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf492b6dfb292a79f0e675.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf492b6dfb292a79f0e675.md
new file mode 100644
index 00000000000..25d6d2447fb
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf492b6dfb292a79f0e675.md
@@ -0,0 +1,174 @@
+---
+id: 63bf492b6dfb292a79f0e675
+title: Step 25
+challengeType: 0
+dashedName: step-25
+---
+
+# --description--
+
+In regex, shorthand character classes allow you to match specific characters without having to write those characters in your pattern. Shorthand character classes are preceded with a backslash (`\`). The character class `\s` will match any whitespace character. Add this to your regex pattern.
+
+# --hints--
+
+Your `regex` variable should be set to the regular expression `/\+-\s/`.
+
+```js
+assert.match(cleanInputString.toString(), /regex\s*=\s*\/\\\+-\\s\//)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+function cleanInputString(str) {
+ const regex = /\+-/;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf4bfe9de3852be51c8f86.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf4bfe9de3852be51c8f86.md
new file mode 100644
index 00000000000..3b18f0aac60
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf4bfe9de3852be51c8f86.md
@@ -0,0 +1,188 @@
+---
+id: 63bf4bfe9de3852be51c8f86
+title: Step 26
+challengeType: 0
+dashedName: step-26
+---
+
+# --description--
+
+Your current pattern won't work just yet. `/+-\s/` looks for `+`, `-`, and a space *in order*. This would match `+- hello` but would not match `+hello`.
+
+To tell the pattern to match each of these characters individually, you need to turn them into a character class. This is done by wrapping the characters you want to match in brackets. For example, this pattern will match the characters `h`, `e`, `l`, or `o`:
+
+```js
+const regex = /[helo]/;
+```
+
+Turn your `+-\s` pattern into a character class. Note that you no longer need to escape the `+` character, because you are using a character class.
+
+# --hints--
+
+Your `regex` variable should be set to the regular expression `[+-\s]`.
+
+```js
+assert.match(cleanInputString.toString(), /regex\s*=\s*\/\[\\?\+-\\s\]\//)
+```
+
+You should not escape the `+` character in your regular expression.
+
+```js
+assert.match(cleanInputString.toString(), /regex\s*=\s*\/\[\+-\\s\]\//);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+function cleanInputString(str) {
+ const regex = /\+-\s/;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf4d351e06432ce9bf3627.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf4d351e06432ce9bf3627.md
new file mode 100644
index 00000000000..30baf30ed58
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf4d351e06432ce9bf3627.md
@@ -0,0 +1,180 @@
+---
+id: 63bf4d351e06432ce9bf3627
+title: Step 27
+challengeType: 0
+dashedName: step-27
+---
+
+# --description--
+
+Regex can also take specific flags to alter the pattern matching behavior. Flags are added after the closing `/`. The `g` flag, which stands for "global", will tell the pattern to continue looking after it has found a match. Here is an example:
+
+```js
+const helloRegex = /hello/g;
+```
+
+Add the `g` flag to your regex pattern.
+
+# --hints--
+
+You should add the `g` flag to your `regex` value.
+
+```js
+assert.match(cleanInputString.toString(), /regex\s*=\s*\/\[\+-\\s\]\/g/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+function cleanInputString(str) {
+ const regex = /[+-\s]/;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf511b85b6082e54dc1573.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf511b85b6082e54dc1573.md
new file mode 100644
index 00000000000..4b35b49f7b9
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf511b85b6082e54dc1573.md
@@ -0,0 +1,199 @@
+---
+id: 63bf511b85b6082e54dc1573
+title: Step 28
+challengeType: 0
+dashedName: step-28
+---
+
+# --description--
+
+Strings have a `.replace()` method which allows you to replace characters in the string with another string. `.replace` takes two arguments. The first is the character sequence to replace – this can either be a string or a regex pattern. The second is the string to replace that sequence with. For example, this would replace all instances of `l` with `1`:
+
+```js
+"hello".replace(/l/g, "1");
+```
+
+Use your `regex` to replace all instances of `+`, `-`, and a space in `str` with an empty string. Return this value.
+
+# --hints--
+
+Your `cleanInputString` should call the `replace` method of `str`.
+
+```js
+assert.match(cleanInputString.toString(), /str\.replace\(/);
+```
+
+You should pass `regex` as the first argument to `replace`.
+
+```js
+assert.match(cleanInputString.toString(), /str\.replace\(\s*regex\s*/);
+```
+
+You should pass `""` as the second argument to `replace`.
+
+```js
+assert.match(cleanInputString.toString(), /str\.replace\(\s*regex\s*,\s*("|')\1\s*\)/);
+```
+
+Your `cleanInputString` function should directly return the result of your `replace` method.
+
+```js
+assert.match(cleanInputString.toString(), /return\s*str\.replace\(\s*regex\s*,\s*("|')\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+--fcc-editable-region--
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5230bccd1c2f5c13e1ce.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5230bccd1c2f5c13e1ce.md
new file mode 100644
index 00000000000..b6eef00a30b
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5230bccd1c2f5c13e1ce.md
@@ -0,0 +1,191 @@
+---
+id: 63bf5230bccd1c2f5c13e1ce
+title: Step 29
+challengeType: 0
+dashedName: step-29
+---
+
+# --description--
+
+In HTML, number inputs allow for exponential notation (such as `1e10`). You need to filter those out.
+
+Start by creating a function called `isInvalidInput` – it should take a single `str` parameter.
+
+# --hints--
+
+You should declare an `isInvalidInput` variable.
+
+```js
+assert.isDefined(isInvalidInput)
+```
+
+`isInvalidInput` should be a function.
+
+```js
+assert.isFunction(isInvalidInput)
+```
+
+`isInvalidInput` should take a single `str` parameter.
+
+```js
+assert.match(isInvalidInput?.toString(), /\(\s*str\s*\)/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf598a4c807930a13a1a27.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf598a4c807930a13a1a27.md
new file mode 100644
index 00000000000..778a809571e
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf598a4c807930a13a1a27.md
@@ -0,0 +1,185 @@
+---
+id: 63bf598a4c807930a13a1a27
+title: Step 30
+challengeType: 0
+dashedName: step-30
+---
+
+# --description--
+
+Declare a `regex` variable, and assign it a regex that matches the character `e`.
+
+# --hints--
+
+Your `isInvalidInput` function should have a `regex` variable.
+
+```js
+assert.match(isInvalidInput.toString(), /regex\s*=/);
+```
+
+Your `regex` variable should be set to `/e/`.
+
+```js
+assert.match(isInvalidInput.toString(), /regex\s*=\s*\/e\//);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+--fcc-editable-region--
+function isInvalidInput(str) {
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5a518d54f63181ab639a.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5a518d54f63181ab639a.md
new file mode 100644
index 00000000000..2bf1aa0f9a3
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5a518d54f63181ab639a.md
@@ -0,0 +1,179 @@
+---
+id: 63bf5a518d54f63181ab639a
+title: Step 31
+challengeType: 0
+dashedName: step-31
+---
+
+# --description--
+
+The `e` in a number input can also be an uppercase `E`. Regex has a flag for this, however – the `i` flag, which stands for "insensitive". This flag makes your pattern case-insensitive. Add the `i` flag to your regex pattern.
+
+# --hints--
+
+Your `regex` value should have the `i` flag.
+
+```js
+assert.match(isInvalidInput.toString(), /regex\s*=\s*\/e\/i/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+--fcc-editable-region--
+function isInvalidInput(str) {
+ const regex = /e/;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5a92fd148d3264d5322b.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5a92fd148d3264d5322b.md
new file mode 100644
index 00000000000..19873a84492
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5a92fd148d3264d5322b.md
@@ -0,0 +1,187 @@
+---
+id: 63bf5a92fd148d3264d5322b
+title: Step 32
+challengeType: 0
+dashedName: step-32
+---
+
+# --description--
+
+Number inputs only allow the `e` to occur between two digits. To match any number, you can use the character class `[0-9]`. This will match any digit between `0` and `9`.
+
+Add this character class before and after `e` in your pattern.
+
+# --hints--
+
+You should add the `[0-9]` character class before `e` in your regular expression.
+
+```js
+assert.match(isInvalidInput.toString(), /regex\s*=\s*\/\[0-9\]e/);
+```
+
+You should add the `[0-9]` character class after `e` in your regular expression.
+
+```js
+assert.match(isInvalidInput.toString(), /regex\s*=\s*\/\[0-9\]e\[0-9\]\//);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+--fcc-editable-region--
+function isInvalidInput(str) {
+ const regex = /e/i;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5adfe2981b332eb007b6.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5adfe2981b332eb007b6.md
new file mode 100644
index 00000000000..75477ddd763
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5adfe2981b332eb007b6.md
@@ -0,0 +1,185 @@
+---
+id: 63bf5adfe2981b332eb007b6
+title: Step 33
+challengeType: 0
+dashedName: step-33
+---
+
+# --description--
+
+The `+` modifier in a regex allows you to match a pattern that occurs one or more times. To match your digit pattern one or more times, add a plus after each of the digit character classes. For example: `[0-9]+`.
+
+# --hints--
+
+You should add the `+` modifier to the character class before `e` in your regular expression.
+
+```js
+assert.match(isInvalidInput.toString(), /regex\s*=\s*\/\[0-9\]\+e/);
+```
+
+You should add the `+` modifier to the character class after `e` in your regular expression.
+
+```js
+assert.match(isInvalidInput.toString(), /regex\s*=\s*\/\[0-9\]\+e\[0-9\]\+\//);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+--fcc-editable-region--
+function isInvalidInput(str) {
+ const regex = /[0-9]e[0-9]/i;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5bcfebff0734593fad19.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5bcfebff0734593fad19.md
new file mode 100644
index 00000000000..95686b3c3a0
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5bcfebff0734593fad19.md
@@ -0,0 +1,185 @@
+---
+id: 63bf5bcfebff0734593fad19
+title: Step 34
+challengeType: 0
+dashedName: step-34
+---
+
+# --description--
+
+There is a shorthand character class to match any digit: `\d`. Replace your `[0-9]` character classes with this shorthand.
+
+# --hints--
+
+You should replace the `[0-9]` character class before `e` with `\d` in your regular expression.
+
+```js
+assert.match(isInvalidInput.toString(), /regex\s*=\s*\/\\d\+e/);
+```
+
+You should replace the `[0-9]` character class after `e` with `\d` in your regular expression.
+
+```js
+assert.match(isInvalidInput.toString(), /regex\s*=\s*\/\\d\+e\\d\+\//);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+--fcc-editable-region--
+function isInvalidInput(str) {
+ const regex = /[0-9]+e[0-9]+/i;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5c438f523a359769106c.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5c438f523a359769106c.md
new file mode 100644
index 00000000000..f6f61282ce9
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5c438f523a359769106c.md
@@ -0,0 +1,194 @@
+---
+id: 63bf5c438f523a359769106c
+title: Step 35
+challengeType: 0
+dashedName: step-35
+---
+
+# --description--
+
+Strings have a `.match()` method, which takes a regex argument. `.match()` will return an array of match results – containing either the first match, or all matches if the global flag is used.
+
+Return the result of calling the `.match()` method on `str` and passing your `regex` variable as the argument. You'll use this match result later on.
+
+# --hints--
+
+Your `isInvalidInput` function should call the `.match()` method on `str`.
+
+```js
+assert.match(isInvalidInput.toString(), /str\.match\(/);
+```
+
+You should pass `regex` as the argument to the `.match()` method.
+
+```js
+assert.match(isInvalidInput.toString(), /str\.match\(\s*regex\s*\)/);
+```
+
+Your `isInvalidInput` function should directly return the result of the `.match()` call.
+
+```js
+assert.match(isInvalidInput.toString(), /return\s+str\.match\(\s*regex\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+--fcc-editable-region--
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5cf03b50bf36cfbe94ea.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5cf03b50bf36cfbe94ea.md
new file mode 100644
index 00000000000..9a3f0df7bef
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63bf5cf03b50bf36cfbe94ea.md
@@ -0,0 +1,194 @@
+---
+id: 63bf5cf03b50bf36cfbe94ea
+title: Step 36
+challengeType: 0
+dashedName: step-36
+---
+
+# --description--
+
+Your next step is to allow users to add entries to the calorie counter. Declare an empty function `addEntry`. This function should not take any parameters.
+
+# --hints--
+
+You should declare an `addEntry` variable.
+
+```js
+assert.isDefined(addEntry);
+```
+
+Your `addEntry` variable should be a function.
+
+```js
+assert.isFunction(addEntry);
+```
+
+Your `addEntry` function should not take any parameters.
+
+```js
+assert.match(addEntry?.toString(), /\(\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1dfbd56c71e278800010c.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1dfbd56c71e278800010c.md
new file mode 100644
index 00000000000..1bc417c8bbb
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1dfbd56c71e278800010c.md
@@ -0,0 +1,198 @@
+---
+id: 63c1dfbd56c71e278800010c
+title: Step 37
+challengeType: 0
+dashedName: step-37
+---
+
+# --description--
+
+You'll need to know which category the entry goes in. Thankfully, you added a dropdown for the user to select a category.
+
+Remember that you queried that dropdown earlier in your JavaScript and assigned it to the `entryDropdown` button. Use concatenation to add `#` to the beginning of the `value` property of `entryDropdown`, and assign that result to a `targetId` variable.
+
+# --hints--
+
+Your `addEntry` function should have a `targetId` variable.
+
+```js
+assert.match(addEntry.toString(), /targetId\s*=/);
+```
+
+Your `targetId` variable should start with the string `#`.
+
+```js
+assert.match(addEntry.toString(), /targetId\s*=\s*('|")#\1/);
+```
+
+You should use concatenation to add `entryDropdown.value` after your `#` string.
+
+```js
+assert.match(addEntry.toString(), /targetId\s*=\s*('|")#\1\s*\+\s*entryDropdown\.value/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e0af28078f2dfad9eb3e.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e0af28078f2dfad9eb3e.md
new file mode 100644
index 00000000000..413b5f76d84
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e0af28078f2dfad9eb3e.md
@@ -0,0 +1,203 @@
+---
+id: 63c1e0af28078f2dfad9eb3e
+title: Step 38
+challengeType: 0
+dashedName: step-38
+---
+
+# --description--
+
+Now you need to target the `.input-container` element within the element that has your `targetId`. Declare a new `targetInputContainer` variable, and assign it the value of `document.querySelector()`. Use concatenation to separate `targetId` and `'.input-container'` with a space, and pass that string to `querySelector()`.
+
+# --hints--
+
+Your `addEntry` function should have a `targetInputContainer` variable.
+
+```js
+assert.match(addEntry.toString(), /targetInputContainer\s*=/);
+```
+
+Your `targetInputContainer` variable should be set to `document.querySelector()`.
+
+```js
+assert.match(addEntry.toString(), /targetInputContainer\s*=\s*document\.querySelector\(/);
+```
+
+You should pass `targetId` to your `querySelector()` method.
+
+```js
+assert.match(addEntry.toString(), /targetInputContainer\s*=\s*document\.querySelector\(\s*targetId\s*/);
+```
+
+You should concatenate `' .input-container'` to `targetId`. Remember to include the space at the beginning of `.input-container`.
+
+```js
+assert.match(addEntry.toString(), /targetInputContainer\s*=\s*document\.querySelector\(\s*targetId\s*\s*\+\s*('|")\s\.input-container\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetId = '#' + entryDropdown.value;
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e1965a898d302e0af4e3.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e1965a898d302e0af4e3.md
new file mode 100644
index 00000000000..914ba9a0f67
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e1965a898d302e0af4e3.md
@@ -0,0 +1,203 @@
+---
+id: 63c1e1965a898d302e0af4e3
+title: Step 39
+challengeType: 0
+dashedName: step-39
+---
+
+# --description--
+
+JavaScript has a feature called template literals , which allow you to interpolate variables directly within a string. Template literals are denoted with backticks ``` `` ```, as opposed to single or double quotes. Variables can be passed in to a template literal by surrounding the variable with `${}` – the value of the variable will be inserted into the string.
+
+For example:
+
+```js
+const name = "Naomi";
+const templateLiteral = `Hello, my name is ${name}~!`;
+console.log(templateLiteral);
+```
+
+The console will show the string "Hello, my name is Naomi~!".
+
+Replace your concatenated string in the `querySelector` with a template literal – be sure to keep the space between your `targetId` variable and `.input-container`.
+
+# --hints--
+
+You should use a template literal in your `querySelector` method.
+
+```js
+assert.match(code, /const\s+targetInputContainer\s*=\s*document\.querySelector\(`.*`\)/);
+```
+
+Your template literal should have the value `{targetId} .input-container`.
+
+```js
+assert.match(code, /const\s+targetInputContainer\s*=\s*document\.querySelector\(`\$\{targetId\}\s\.input-container`\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetId = '#' + entryDropdown.value;
+ const targetInputContainer = document.querySelector(targetId + ' .input-container');
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e5b4b3c8a031def3bd65.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e5b4b3c8a031def3bd65.md
new file mode 100644
index 00000000000..6aeab26c100
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e5b4b3c8a031def3bd65.md
@@ -0,0 +1,197 @@
+---
+id: 63c1e5b4b3c8a031def3bd65
+title: Step 40
+challengeType: 0
+dashedName: step-40
+---
+
+# --description--
+
+Thanks to template literals, you actually don't need the `targetId` variable at all. Remove that variable, and update your template literal to replace `targetId` with `entryDropdown.value` – remember to add `#` before that, in the string.
+
+# --hints--
+
+You should remove the `targetId` variable.
+
+```js
+assert.notMatch(addEntry.toString(), /targetId\s*=/);
+```
+
+You should replace the `targetId` reference in your template literal with `entryDropdown.value`.
+
+```js
+assert.match(code, /const\s+targetInputContainer\s*=\s*document\.querySelector\(`#?\$\{entryDropdown\.value\}\s\.input-container`\s*\)/);
+```
+
+You should add `#` at the beginning of your template literal.
+
+```js
+assert.match(code, /const\s+targetInputContainer\s*=\s*document\.querySelector\(`#\$\{entryDropdown\.value\}\s\.input-container`\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetId = '#' + entryDropdown.value;
+ const targetInputContainer = document.querySelector(`${targetId} .input-container`);
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e704ee12703347625900.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e704ee12703347625900.md
new file mode 100644
index 00000000000..b658496aeee
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c1e704ee12703347625900.md
@@ -0,0 +1,197 @@
+---
+id: 63c1e704ee12703347625900
+title: Step 41
+challengeType: 0
+dashedName: step-41
+---
+
+# --description--
+
+You will want to number the entries a user adds. Declare an `entryNumber` variable and give it the value of `targetInputContainer.querySelectorAll()`. You do not need to pass an argument to the query selector yet.
+
+# --hints--
+
+You should have an `entryNumber` variable.
+
+```js
+assert.match(addEntry.toString(), /entryNumber\s*=/);
+```
+
+Your `entryNumber` variable should have the value of `targetInputContainer.querySelectorAll()`.
+
+```js
+assert.match(addEntry.toString(), /entryNumber\s*=\s*targetInputContainer\.querySelectorAll\(/);
+```
+
+You should not pass an argument to `querySelectorAll()`.
+
+```js
+assert.match(addEntry.toString(), /entryNumber\s*=\s*targetInputContainer\.querySelectorAll\(\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2164c0df38a382062c4af.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2164c0df38a382062c4af.md
new file mode 100644
index 00000000000..15622f17e14
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2164c0df38a382062c4af.md
@@ -0,0 +1,201 @@
+---
+id: 63c2164c0df38a382062c4af
+title: Step 42
+challengeType: 0
+dashedName: step-42
+---
+
+# --description--
+
+Each entry will have a text input for the entry's name, and a number input for the calories. To get a count of the number of entries, you can query by text inputs. Note that you cannot query by number inputs, as you have an extra number input for the user's calorie budget.
+
+Pass the string `input[type="text"]` to the `querySelectorAll()` method. Remember that you will need to use single quotes for your string, so that you can use double quotes within.
+
+This will return a `NodeList` of all the text inputs in the form. You can then access the `length` property of the `NodeList` to get the number of entries. Do this on the same line.
+
+# --hints--
+
+You should pass the string `input[type="text"]` to the `querySelectorAll()` method.
+
+```js
+assert.match(addEntry.toString(), /entryNumber\s*=\s*targetInputContainer\.querySelectorAll\(\s*'input\[type="text"]'\)/)
+```
+
+You should access the `length` property of your `querySelectorAll()`.
+
+```js
+assert.match(addEntry.toString(), /\.querySelectorAll\(\s*'input\[type="text"]'\)\.length/)
+```
+
+Your `entryNumber` variable should be the `length` of the `querySelectorAll`.
+
+```js
+assert.match(addEntry.toString(), /entryNumber\s*=\s*targetInputContainer\.querySelectorAll\(\s*'input\[type="text"]'\)\.length/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll();
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c216da562fbb3957b9cb2c.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c216da562fbb3957b9cb2c.md
new file mode 100644
index 00000000000..ae9177aa122
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c216da562fbb3957b9cb2c.md
@@ -0,0 +1,192 @@
+---
+id: 63c216da562fbb3957b9cb2c
+title: Step 43
+challengeType: 0
+dashedName: step-43
+---
+
+# --description--
+
+Now you need to build your dynamic HTML string to add to the webpage. Declare a new `HTMLString` variable, and assign it an empty template literal string.
+
+# --hints--
+
+Your `addEntry` function should have an `HTMLString` variable.
+
+```js
+assert.match(addEntry.toString(), /HTMLString\s*=/)
+```
+
+Your `HTMLString` should be an empty template literal.
+
+```js
+assert.match(code, /HTMLString\s*=\s*``/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length;
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2171c1e5b6e3aa51768d0.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2171c1e5b6e3aa51768d0.md
new file mode 100644
index 00000000000..e8ced7f3436
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2171c1e5b6e3aa51768d0.md
@@ -0,0 +1,198 @@
+---
+id: 63c2171c1e5b6e3aa51768d0
+title: Step 44
+challengeType: 0
+dashedName: step-44
+---
+
+# --description--
+
+Start your `HTMLString` with a new line, then create a `label` element. Give that element the text `Entry # Name`, using your template literal syntax to replace `#` with the value of `entryNumber`.
+
+# --hints--
+
+Your `HTMLString` variable should start with a new line.
+
+```js
+assert.match(code, /HTMLString\s*=\s*`\n/);
+```
+
+You should add a `label` element on the new line.
+
+```js
+assert.match(code, /HTMLString\s*=\s*`\n\s*.*<\/label>/);
+```
+
+Your `label` element should have the text `Entry ${entryNumber} Name`.
+
+```js
+assert.match(code, /HTMLString\s*=\s*`\n\s*Entry\s\$\{entryNumber\}\sName<\/label>/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length;
+ const HTMLString = ``;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21774193de43bbc6a769f.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21774193de43bbc6a769f.md
new file mode 100644
index 00000000000..f78a3d0252c
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21774193de43bbc6a769f.md
@@ -0,0 +1,193 @@
+---
+id: 63c21774193de43bbc6a769f
+title: Step 45
+challengeType: 0
+dashedName: step-45
+---
+
+# --description--
+
+Give your `label` element a `for` attribute with the value `X-#-name`, where `X` is the `value` of the `entryDropdown` element and `#` is the value of `entryNumber`. Remember that HTML attributes should be wrapped in double quotes.
+
+# --hints--
+
+Your `label` element should have a `for` attribute set to `${entryDropdown.value}-${entryNumber}-name`.
+
+```js
+assert.match(code, /HTMLString\s*=\s*`\n\s*/)
+```
+
+Your `label` element should have the same text as before.
+
+```js
+assert.match(code, /HTMLString\s*=\s*`\n\s*Entry\s\$\{entryNumber\}\sName<\/label>/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length;
+ const HTMLString = `
+ Entry ${entryNumber} Name `;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c217ccd939053ce4fa16d6.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c217ccd939053ce4fa16d6.md
new file mode 100644
index 00000000000..42ee9b19109
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c217ccd939053ce4fa16d6.md
@@ -0,0 +1,217 @@
+---
+id: 63c217ccd939053ce4fa16d6
+title: Step 46
+challengeType: 0
+dashedName: step-46
+---
+
+# --description--
+
+After your `label` element, and on a new line in your template string, create an `input` element. Give it a `type` attribute set to `text`, a `placeholder` attribute set to `Name`, and an `id` attribute that matches the `for` attribute of your `label` element.
+
+# --hints--
+
+You should not modify your `label` element.
+
+```js
+assert.match(code, /HTMLString\s*=\s*`\n\s*Entry\s\$\{entryNumber\}\sName<\/label>/);
+```
+
+You should add an `input` element on a new line.
+
+```js
+assert.match(code, /HTMLString\s*=\s*`\n\s*Entry\s\$\{entryNumber\}\sName<\/label>\n\s* /)[0];
+assert.include(inputAttributes, 'type="text"');
+```
+
+Your `input` element should have a `placeholder` attribute set to `Name`.
+
+```js
+const HTMLstring = code.split("HTMLString =")[1];
+const inputAttributes = HTMLstring.match(/ /)[0];
+assert.include(inputAttributes, 'placeholder="Name"');
+```
+
+Your `input` element should have an `id` attribute set to `${entryDropdown.value}-${entryNumber}-name`.
+
+```js
+const HTMLstring = code.split("HTMLString =")[1];
+const inputAttributes = HTMLstring.match(/ /)[0];
+assert.include(inputAttributes, 'id="${entryDropdown.value}-${entryNumber}-name"');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length;
+ const HTMLString = `
+ Entry ${entryNumber} Name `;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21839f56eaf3ef4e027c4.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21839f56eaf3ef4e027c4.md
new file mode 100644
index 00000000000..cfeec0927c4
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21839f56eaf3ef4e027c4.md
@@ -0,0 +1,228 @@
+---
+id: 63c21839f56eaf3ef4e027c4
+title: Step 47
+challengeType: 0
+dashedName: step-47
+---
+
+# --description--
+
+Create another `label` element (on a new line) at the end of your `HTMLString`. This `label` should have the text `Entry # Calories`, using your template literal syntax to replace `#` with the value of `entryNumber`, and the `for` attribute set to `X-#-calories`, where `X` is the `value` of `entryDropdown` and `#` is the value of `entryNumber`.
+
+# --hints--
+
+You should have two `label` elements in your `HTMLString`.
+
+```js
+const HTMLstring = code.split("HTMLString =")[1];
+assert.equal(HTMLstring.match(/.*<\/label>/g)[1];
+assert.match(label, //)
+```
+
+Your new `label` element should have the text `Entry ${entryNumber} Calories`.
+
+```js
+const HTMLstring = code.split("HTMLString =")[1];
+const label = HTMLstring.match(/.*<\/label>/g)[1];
+assert.match(label, /Entry\s\$\{entryNumber\}\sCalories<\/label>/);
+```
+
+You should not modify your existing elements.
+
+```js
+const HTMLstring = code.split("HTMLString =")[1];
+assert.match(HTMLstring, /`\n\s*Entry\s\$\{entryNumber\}\sName<\/label>\n\s* \n\s*Entry\s\$\{entryNumber\}\sCalories<\/label>/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+ `;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2187f55eb0f400269568f.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2187f55eb0f400269568f.md
new file mode 100644
index 00000000000..f0fa5f37c19
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2187f55eb0f400269568f.md
@@ -0,0 +1,238 @@
+---
+id: 63c2187f55eb0f400269568f
+title: Step 48
+challengeType: 0
+dashedName: step-48
+---
+
+# --description--
+
+Finally, on a new line after your second `label`, create another `input` element. Give this one a `type` attribute set to `number`, a `min` attribute set to `0` (to ensure negative calories cannot be added), a `placeholder` attribute set to `Calories`, and an `id` attribute that matches the `for` attribute of your second `label` element.
+
+# --hints--
+
+You should have two `input` elements in your `HTMLString`.
+
+```js
+const HTMLstring = code.split("HTMLString =")[1];
+assert.equal(HTMLstring.match(/ ]*>/g)[1];
+assert.include(inputAttributes, 'type="number"');
+```
+
+Your `input` element should have a `placeholder` attribute set to `Calories`.
+
+```js
+const HTMLstring = code.split("HTMLString =")[1];
+const inputAttributes = HTMLstring.match(/ ]*>/g)[1];
+assert.include(inputAttributes, 'placeholder="Calories"');
+```
+
+Your `input` element should have an `id` attribute set to `${entryDropdown.value}-${entryNumber}-name`.
+
+```js
+const HTMLstring = code.split("HTMLString =")[1];
+const inputAttributes = HTMLstring.match(/ ]*>/g)[1];
+assert.include(inputAttributes, 'id="${entryDropdown.value}-${entryNumber}-calories"');
+```
+
+Your `input` element should have a `min` attribute set to `0`.
+
+```js
+const HTMLstring = code.split("HTMLString =")[1];
+const inputAttributes = HTMLstring.match(/ ]*>/g)[1];
+assert.include(inputAttributes, 'min="0"');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories `;
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c218c028c56a411b2a379a.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c218c028c56a411b2a379a.md
new file mode 100644
index 00000000000..36835a69413
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c218c028c56a411b2a379a.md
@@ -0,0 +1,208 @@
+---
+id: 63c218c028c56a411b2a379a
+title: Step 49
+challengeType: 0
+dashedName: step-49
+---
+
+# --description--
+
+Finally, add your new `HTMLString` to the `targetInputContainer` by using the `innerHTML` property. Remember to use the `+=` operator to add to the existing HTML instead of replacing it.
+
+# --hints--
+
+Your `addEntry` function should access the `innerHTML` property of `targetInputContainer`.
+
+```js
+assert.match(addEntry.toString(), /targetInputContainer\.innerHTML/);
+```
+
+You should use the `+=` operator on `targetInputContainer.innerHTML`.
+
+```js
+assert.match(addEntry.toString(), /targetInputContainer\.innerHTML\s*\+=/);
+```
+
+You should add your `HTMLString` to the `innerHTML` of the `targetInputContainer` element.
+
+```js
+assert.match(addEntry.toString(), /targetInputContainer\.innerHTML\s*\+=\s*HTMLString/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+
+}
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2194dce265f429300c8b1.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2194dce265f429300c8b1.md
new file mode 100644
index 00000000000..ebb6b922e2b
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c2194dce265f429300c8b1.md
@@ -0,0 +1,200 @@
+---
+id: 63c2194dce265f429300c8b1
+title: Step 51
+challengeType: 0
+dashedName: step-51
+---
+
+# --description--
+
+Try adding a couple of entries to the `Breakfast` category, and you may notice some bugs! The first thing we need to fix is the entry counts – the first entry should have a count of `1`, not `0`.
+
+This bug occurs because you are querying for `input[type="text"]` elements *before* adding the new entry to the page. To fix this, update your `entryNumber` variable to be the value of the `length` of the query plus `1`. Add this on your declaration line, not in your template strings.
+
+# --hints--
+
+You should add `1` to the `.length` of your `querySelectorAll()` method.
+
+```js
+assert.match(addEntry.toString(), /entryNumber\s*=\s*targetInputContainer\.querySelectorAll\(\s*'input\[type="text"]'\)\.length\s*\+\s*1/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.innerHTML += HTMLString;
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21c17fa8fd6447ff0389d.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21c17fa8fd6447ff0389d.md
new file mode 100644
index 00000000000..2d0ccd9e339
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21c17fa8fd6447ff0389d.md
@@ -0,0 +1,212 @@
+---
+id: 63c21c17fa8fd6447ff0389d
+title: Step 52
+challengeType: 0
+dashedName: step-52
+---
+
+# --description--
+
+Your other bug occurs if you add a `Breakfast` entry, fill it in, then add a second `Breakfast` entry. You'll see that the values you added disappeared.
+
+This is because you are updating `innerHTML` directly, which does not preserve your input content. Change your `innerHTML` assignment to use the `insertAdjacentHTML()` method of `targetInputContainer` instead. Do not pass any arguments yet.
+
+# --hints--
+
+You should not access the `innerHTML` property of `targetInputContainer`.
+
+```js
+assert.notMatch(addEntry.toString(), /targetInputContainer\.innerHTML/);
+```
+
+You should call the `insertAdjacentHTML()` method of `targetInputContainer`.
+
+```js
+assert.match(addEntry.toString(), /targetInputContainer\.insertAdjacentHTML\(/);
+```
+
+You should not pass any arguments to `insertAdjacentHTML()`.
+
+```js
+assert.match(addEntry.toString(), /targetInputContainer\.insertAdjacentHTML\(\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.innerHTML += HTMLString;
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21cd2c34541469f5700a9.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21cd2c34541469f5700a9.md
new file mode 100644
index 00000000000..78b1d7d6116
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21cd2c34541469f5700a9.md
@@ -0,0 +1,208 @@
+---
+id: 63c21cd2c34541469f5700a9
+title: Step 53
+challengeType: 0
+dashedName: step-53
+---
+
+# --description--
+
+The `insertAdjacentHtml` method takes two arguments. The first argument is a string that specifies the position of the inserted element. The second argument is a string containing the HTML to be inserted.
+
+For the first argument, pass the string `beforeend` to insert the new element as the last child of `targetInputContainer`.
+
+For the second argument, pass your `HTMLString` variable.
+
+# --hints--
+
+You should pass the string `beforeend` as the first argument to `insertAdjacentHTML`.
+
+```js
+assert.match(addEntry.toString(), /insertAdjacentHTML\(\s*('|")beforeend\1/);
+```
+
+You should pass your `HTMLString` variable as the second argument to `insertAdjacentHTML`.
+
+```js
+assert.match(addEntry.toString(), /insertAdjacentHTML\(\s*('|")beforeend\1\s*,\s*HTMLString\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+--fcc-editable-region--
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML();
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21d4f48267a47c2946788.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21d4f48267a47c2946788.md
new file mode 100644
index 00000000000..501371edf5e
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21d4f48267a47c2946788.md
@@ -0,0 +1,216 @@
+---
+id: 63c21d4f48267a47c2946788
+title: Step 54
+challengeType: 0
+dashedName: step-54
+---
+
+# --description--
+
+Great! Now you can add entries without losing your previous inputs.
+
+Your next step is to write a function that will get the calorie counts from the user's entries.
+
+Declare a `getCaloriesFromInputs` function, and give it a parameter called `list`.
+
+# --hints--
+
+You should declare a `getCaloriesFromInputs` variable.
+
+```js
+assert.isDefined(getCaloriesFromInputs);
+```
+
+Your `getCaloriesFromInputs` variable should be a function.
+
+```js
+assert.isFunction(getCaloriesFromInputs);
+```
+
+Your `getCaloriesFromInputs` function should take a parameter called `list`.
+
+```js
+assert.match(getCaloriesFromInputs?.toString(), /\(\s*list\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21dea919c8e4adb0df8e8.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21dea919c8e4adb0df8e8.md
new file mode 100644
index 00000000000..b4f31e92cea
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c21dea919c8e4adb0df8e8.md
@@ -0,0 +1,212 @@
+---
+id: 63c21dea919c8e4adb0df8e8
+title: Step 50
+challengeType: 0
+dashedName: step-50
+---
+
+# --description--
+
+In the Role Playing Game project, you learned how to set a button's behavior by editing its `onclick` property. You can also edit an element's behavior by adding an event listener.
+
+Call the `.addEventListener()` method of the `addEntryButton`. This takes two arguments. The first is the event to listen to – you should pass the string `click`. The second is the callback function, or the function that runs when the event is triggered. Pass the `addEntry` function as the second argument. Note that you should not *call* `addEntry`, but pass the variable (or function reference ) directly.
+
+# --hints--
+
+You should call the `.addEventListener()` method of the `addEntryButton`.
+
+```js
+assert.match(code, /addEntryButton\.addEventListener\(/);
+```
+
+You should pass `click` as the first argument to the `.addEventListener()` method.
+
+```js
+assert.match(code, /addEntryButton\.addEventListener\(\s*('|")click\1\s*/);
+```
+
+You should pass `addEntry` as the second argument to the `.addEventListener()` method.
+
+```js
+assert.match(code, /addEntryButton\.addEventListener\(\s*('|")click\1\s*,\s*addEntry\s*/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.innerHTML += HTMLString;
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8ab51214c8c1f1b9a49f7.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8ab51214c8c1f1b9a49f7.md
new file mode 100644
index 00000000000..8d47f896df1
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8ab51214c8c1f1b9a49f7.md
@@ -0,0 +1,216 @@
+---
+id: 63c8ab51214c8c1f1b9a49f7
+title: Step 55
+challengeType: 0
+dashedName: step-55
+---
+
+# --description--
+
+In your new function, declare a `calories` variable and assign it the value `0`. Use `let` to declare it, since you will be reassigning it later.
+
+# --hints--
+
+You should declare a `calories` variable.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /calories\s*=/);
+```
+
+Your `calories` variable should be assigned the value `0`.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /calories\s*=\s*0/);
+```
+
+You should declare your `calories` variable with `let`.
+
+```js
+// babel transforms the code, so we gotta do a hack here
+const getCaloriesFromInputsString = code.split('function getCaloriesFromInputs')[1];
+assert.match(getCaloriesFromInputsString, /let\s+calories\s*=\s*0/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function getCaloriesFromInputs(list) {
+
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8ad0cd8f1e5201c4ef2e4.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8ad0cd8f1e5201c4ef2e4.md
new file mode 100644
index 00000000000..169ea135fca
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8ad0cd8f1e5201c4ef2e4.md
@@ -0,0 +1,224 @@
+---
+id: 63c8ad0cd8f1e5201c4ef2e4
+title: Step 56
+challengeType: 0
+dashedName: step-56
+---
+
+# --description--
+
+The `list` parameter is going to be the result of a query selector, which will return a `NodeList`. A `NodeList` is an array-like which contains the elements that match the query selector.
+
+You'll need to loop through these elements, so start by creating a `for` loop. Your iterator `i` should start at `0`, continue while it is less than the length of the list, and increment by `1` each iteration.
+
+# --hints--
+
+Your `getCaloriesFromInputs` function should have a `for` loop.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /for\s*\(/g);
+```
+
+Your `for` loop should initialize a variable called `i` to `0`.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;/g);
+```
+
+Your `for` loop should have a condition that checks if `i` is less than the length of `list`.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;\s*i\s*<\s*list\.length\s*;/g);
+```
+
+Your `for` loop should increment `i` by `1` each time it runs. Use the increment operator for this.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /for\s*\(\s*(let|var)\s+i\s*=\s*0\s*;\s*i\s*<\s*list\.length\s*;\s*i\s*\+\+\s*\)/g);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8b0187cceff21c8389543.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8b0187cceff21c8389543.md
new file mode 100644
index 00000000000..645fcaa4d24
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8b0187cceff21c8389543.md
@@ -0,0 +1,234 @@
+---
+id: 63c8b0187cceff21c8389543
+title: Step 57
+challengeType: 0
+dashedName: step-57
+---
+
+# --description--
+
+The `NodeList` values you will pass to `list` will consist of `input` elements. So you will want to look at the `value` attribute of each element.
+
+Assign the `value` of the element in `list` at index `i` to a variable called `currVal`.
+
+# --hints--
+
+You should have a `currVal` variable.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /currVal\s*=/);
+```
+
+You should access the element in `list` at index `i` using bracket notation.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /list\[i\]/);
+```
+
+You should access the `value` attribute of the element in `list` at index `i`.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /list\[i\]\.value/);
+```
+
+You should assign the `value` of the element in `list` at index `i` to a variable called `currVal`.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /currVal\s*=\s*list\[i\]\.value/);
+```
+
+Your `currVal` assignment should be in your `for` loop.
+
+```js
+// another hack, because the loop protection injects stuff
+const getCaloriesString = code.split("function getCaloriesFromInputs")[1];
+assert.match(getCaloriesString, /for\s*\(\s*let\s+i\s*=\s*0\s*;\s*i\s*<\s*list\.length\s*;\s*i\s*\+\+\s*\)\s*\{\s*const|let\s*currVal\s*=\s*list\[i\]\.value/g);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+
+ }
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8be904ffff922f3c6f8d0.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8be904ffff922f3c6f8d0.md
new file mode 100644
index 00000000000..ae8ef40dd20
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8be904ffff922f3c6f8d0.md
@@ -0,0 +1,221 @@
+---
+id: 63c8be904ffff922f3c6f8d0
+title: Step 58
+challengeType: 0
+dashedName: step-58
+---
+
+# --description--
+
+Remember that you wrote a function earlier to clean the user's input? You'll need to use that function here.
+
+Update your `currVal` declaration to be the result of calling `cleanInputString` with `list[i].value`.
+
+# --hints--
+
+Your `getCaloriesFromInputs` function should call your `cleanInputString` function.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /cleanInputString\(/);
+```
+
+You should pass `list[i].value` as the parameter for `cleanInputString`.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /cleanInputString\(\s*list\[i\]\.value\)/);
+```
+
+You should assign the result of your `cleanInputString` call to your `currVal` variable.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /currVal\s*=\s*cleanInputString\(\s*list\[i\]\.value\)/);
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = list[i].value;
+ }
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8c00bfb671b23f9de4159.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8c00bfb671b23f9de4159.md
new file mode 100644
index 00000000000..a994632ff24
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8c00bfb671b23f9de4159.md
@@ -0,0 +1,219 @@
+---
+id: 63c8c00bfb671b23f9de4159
+title: Step 59
+challengeType: 0
+dashedName: step-59
+---
+
+# --description--
+
+You also need to confirm the input is valid. Declare an `invalidInputMatch` variable, and assign it the result of calling your `isInvalidInput` function with `currVal` as the argument.
+
+# --hints--
+
+You should declare an `invalidInputMatch` variable.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /invalidInputMatch\s*=/);
+```
+
+You should assign the result of calling `isInvalidInput` to your `invalidInputMatch` variable.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /invalidInputMatch\s*=\s*isInvalidInput\(/);
+```
+
+You should pass `currVal` as the parameter to `isInvalidInput`.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /invalidInputMatch\s*=\s*isInvalidInput\(\s*currVal\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+
+ }
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8c15fd337ad24b9b68049.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8c15fd337ad24b9b68049.md
new file mode 100644
index 00000000000..673507a9811
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c8c15fd337ad24b9b68049.md
@@ -0,0 +1,233 @@
+---
+id: 63c8c15fd337ad24b9b68049
+title: Step 60
+challengeType: 0
+dashedName: step-60
+---
+
+# --description--
+
+Remember that your `isInvalidInput` function returns `String.match`, which is an array of matches or `null` if no matches are found.
+
+In JavaScript, values can either be truthy or falsy . A value is truthy if it evaluates to `true` when converted to a Boolean. A value is falsy if it evaluates to `false` when converted to a Boolean. `null` is an example of a falsy value.
+
+You need to check if `invalidInputMatch` is truthy – you can do this by passing the variable directly to your `if` condition (without a comparison operator). Here's an example of checking the truthiness of `helloWorld`.
+
+```js
+if (helloWorld) {
+
+}
+```
+
+Add an `if` statement that checks if `invalidInputMatch` is truthy.
+
+# --hints--
+
+You should add an `if` statement to your `getCaloriesFromInputs` function.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /if\s*\(/);
+```
+
+You should check the truthiness of `invalidInputMatch` in your `if` condition.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /if\s*\(\s*invalidInputMatch\s*\)/);
+```
+
+Your `if` statement should be inside your `for` loop.
+
+```js
+assert.isBelow(getCaloriesFromInputs.toString().indexOf("for"), getCaloriesFromInputs.toString().indexOf("if"));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+
+ }
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bc53735149084390e5d0.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bc53735149084390e5d0.md
new file mode 100644
index 00000000000..89e6408af48
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bc53735149084390e5d0.md
@@ -0,0 +1,226 @@
+---
+id: 63c9bc53735149084390e5d0
+title: Step 61
+challengeType: 0
+dashedName: step-61
+---
+
+# --description--
+
+Browsers have a built in `alert()` function, which you can use to display a pop-up message to the user. The message to display is passed as the argument to the `alert()` function.
+
+Using a template literal, in your `if` block, call the `alert()` function to tell the user `Invalid Input: `, followed by the first value in the `invalidInputMatch` array.
+
+# --hints--
+
+You should call the `alert()` function in your `if` block.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /if\s*\(\s*invalidInputMatch\s*\)\s*\{\s*alert\(/);
+```
+
+You should use a template literal to pass the `Invalid Input: ` message to the `alert()` function.
+
+```js
+// because it transforms template literals...
+assert.match(code.split("function getCaloriesFromInputs")[1], /alert\(`Invalid Input: /);
+```
+
+You should use template literal syntax to display the first value in the `invalidInputMatch` array after the `Invalid Input: ` text.
+
+```js
+assert.match(code.split("function getCaloriesFromInputs")[1], /alert\(`Invalid Input: \${invalidInputMatch\[0\]}`\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+
+ }
+ }
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bcc26219e7090da0f549.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bcc26219e7090da0f549.md
new file mode 100644
index 00000000000..8857c49a4af
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bcc26219e7090da0f549.md
@@ -0,0 +1,218 @@
+---
+id: 63c9bcc26219e7090da0f549
+title: Step 62
+challengeType: 0
+dashedName: step-62
+---
+
+# --description--
+
+Still within your `if` block, set `isError` to `true` and return `null`.
+
+# --hints--
+
+After your `alert`, you should set `isError` to `true`.
+
+```js
+assert.match(code.split("function getCaloriesFromInputs")[1], /alert\(`Invalid Input: \${invalidInputMatch\[0\]}`\s*\);\s*isError\s*=\s*true/);
+```
+
+After you modify `isError`, you should `return` the value `null`.
+
+```js
+assert.match(code.split("function getCaloriesFromInputs")[1], /alert\(`Invalid Input: \${invalidInputMatch\[0\]}`\s*\);\s*isError\s*=\s*true;?\s*return\s+null;?\s*\}/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+
+ }
+ }
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bce376ca4f09c15a3768.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bce376ca4f09c15a3768.md
new file mode 100644
index 00000000000..9e327dd56a4
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bce376ca4f09c15a3768.md
@@ -0,0 +1,234 @@
+---
+id: 63c9bce376ca4f09c15a3768
+title: Step 63
+challengeType: 0
+dashedName: step-63
+---
+
+# --description--
+
+Remember that `return` ends the execution of a function. After your `if` block, you need to handle the logic for when the input is valid. Because your `if` statement returns a value, you do not need an `else` statement.
+
+Use the addition assignment operator to add `currVal` to your `calories` total. You'll need to use the `Number` constructor to convert `currVal` to a number.
+
+# --hints--
+
+You should not add an `else` statement.
+
+```js
+assert.notMatch(getCaloriesFromInputs.toString(), /else/);
+```
+
+After your `if` statement, you should use the addition assignment operator on `calories`.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /if.*}\s*calories\s*\+=/s);
+```
+
+You should pass `currVal` to the `Number()` constructor.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /Number\(\s*currVal\s*\)/);
+```
+
+You should add the value of `Number(currVal)` to `calories`.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /calories\s*\+=\s*Number\(\s*currVal\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+
+ }
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bdd916e0c10af01ed8d7.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bdd916e0c10af01ed8d7.md
new file mode 100644
index 00000000000..ba37342ef6c
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bdd916e0c10af01ed8d7.md
@@ -0,0 +1,221 @@
+---
+id: 63c9bdd916e0c10af01ed8d7
+title: Step 64
+challengeType: 0
+dashedName: step-64
+---
+
+# --description--
+
+After your `for` loop has completed, return the `calories` value.
+
+# --hints--
+
+You should `return` the `calories` value.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /return\s+calories/);
+```
+
+Your new `return` statement should come after your `for` loop.
+
+```js
+assert.match(getCaloriesFromInputs.toString(), /calories\s*\+=\sNumber\(currVal\);\n\s*}\n\s*return\s+calories/)
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9be334f4a050c0b94bc93.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9be334f4a050c0b94bc93.md
new file mode 100644
index 00000000000..2a4f6d26012
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9be334f4a050c0b94bc93.md
@@ -0,0 +1,229 @@
+---
+id: 63c9be334f4a050c0b94bc93
+title: Step 65
+challengeType: 0
+dashedName: step-65
+---
+
+# --description--
+
+Now it's time to start putting it all together. Declare an empty `calculateCalories` function, which takes a parameter named `e`. This function will be another event listener, so the first argument passed will be the browser event – `e` is a common name for this parameter.
+
+# --hints--
+
+You should declare a `calculateCalories` variable.
+
+```js
+assert.isDefined(calculateCalories);
+```
+
+Your `calculateCalories` variable should be a function.
+
+```js
+assert.isFunction(calculateCalories);
+```
+
+Your `calculateCalories` function should take an `e` argument.
+
+```js
+assert.match(calculateCalories?.toString(), /\(e\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bef7fec05c0d38853828.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bef7fec05c0d38853828.md
new file mode 100644
index 00000000000..13d558d532c
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bef7fec05c0d38853828.md
@@ -0,0 +1,227 @@
+---
+id: 63c9bef7fec05c0d38853828
+title: Step 66
+challengeType: 0
+dashedName: step-66
+---
+
+# --description--
+
+You will be attaching this function to the `submit` event of the form. The `submit` event is triggered when the form is submitted. The default action of the `submit` event is to reload the page. You need to prevent this default action using the `preventDefault()` method of your `e` parameter.
+
+Add a line to your `calculateCalories` function that calls the `preventDefault()` method on the `e` parameter. Then, reset your global error flag to `false`.
+
+# --hints--
+
+Your `calculateCalories` function should call `e.preventDefault()`.
+
+```js
+assert.match(calculateCalories.toString(), /e\.preventDefault\(\)/);
+```
+
+Your `calculateCalories` function should reset the global error flag to `false`.
+
+```js
+assert.match(calculateCalories.toString(), /isError\s*=\s*false/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bf80558d780e848b2987.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bf80558d780e848b2987.md
new file mode 100644
index 00000000000..4e4da977f9e
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9bf80558d780e848b2987.md
@@ -0,0 +1,236 @@
+---
+id: 63c9bf80558d780e848b2987
+title: Step 67
+challengeType: 0
+dashedName: step-67
+---
+
+# --description--
+
+Your function needs to get the values from the entries the user has added.
+
+Declare a `breakfastNumberInputs` variable, and give it the value of calling `document.querySelectorAll()` with the selector `#breakfast input[type=number]`. This will return any `number` inputs that are in the `#breakfast` element.
+
+# --hints--
+
+You should declare a `breakfastNumberInputs` variable.
+
+```js
+assert.match(calculateCalories.toString(), /breakfastNumberInputs\s*=/);
+```
+
+You should call `document.querySelectorAll()` with `#breakfast input[type=number]`.
+
+```js
+assert.match(calculateCalories.toString(), /document\.querySelectorAll\(('|")#breakfast input\[type=number\]\1\)/);
+```
+
+You should assign the result of your `odocument.querySelectorAll()` call to `breakfastNumberInputs`.
+
+```js
+assert.match(calculateCalories.toString(), /breakfastNumberInputs\s*=\s*document\.querySelectorAll\(('|")#breakfast input\[type=number\]\1\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c09a7daa4f0ff92c4023.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c09a7daa4f0ff92c4023.md
new file mode 100644
index 00000000000..84fd6422b00
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c09a7daa4f0ff92c4023.md
@@ -0,0 +1,235 @@
+---
+id: 63c9c09a7daa4f0ff92c4023
+title: Step 68
+challengeType: 0
+dashedName: step-68
+---
+
+# --description--
+
+Using that same syntax, query your `number` inputs in the `#lunch` element and assign them to `lunchNumberInputs`.
+
+# --hints--
+
+You should declare a `lunchNumberInputs` variable.
+
+```js
+assert.match(calculateCalories.toString(), /lunchNumberInputs\s*=/);
+```
+
+You should call `document.querySelectorAll()` with `#lunch input[type=number]`.
+
+```js
+assert.match(calculateCalories.toString(), /document\.querySelectorAll\(('|")#lunch input\[type=number\]\1\)/);
+```
+
+You should assign the result of your `document.querySelectorAll()` call to `lunchNumberInputs`.
+
+```js
+assert.match(calculateCalories.toString(), /lunchNumberInputs\s*=\s*document\.querySelectorAll\(('|")#lunch input\[type=number\]\1\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c0d0857f0a10a57af936.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c0d0857f0a10a57af936.md
new file mode 100644
index 00000000000..8868dc1350c
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c0d0857f0a10a57af936.md
@@ -0,0 +1,272 @@
+---
+id: 63c9c0d0857f0a10a57af936
+title: Step 69
+challengeType: 0
+dashedName: step-69
+---
+
+# --description--
+
+Following the same pattern, query for your `number` inputs in the `#dinner`, `#snacks`, and `#exercise` elements. Assign them to variables following the naming scheme of the previous two.
+
+# --hints--
+
+You should declare a `dinnerNumberInputs` variable.
+
+```js
+assert.match(calculateCalories.toString(), /dinnerNumberInputs\s*=/);
+```
+
+You should call `document.querySelectorAll()` with `#dinner input[type=number]`.
+
+```js
+assert.match(calculateCalories.toString(), /document\.querySelectorAll\(('|")#dinner input\[type=number\]\1\)/);
+```
+
+You should assign the result of your `document.querySelectorAll()` call to `dinnerNumberInputs`.
+
+```js
+assert.match(calculateCalories.toString(), /dinnerNumberInputs\s*=\s*document\.querySelectorAll\(('|")#dinner input\[type=number\]\1\)/);
+```
+
+You should declare a `snacksNumberInputs` variable.
+
+```js
+assert.match(calculateCalories.toString(), /snacksNumberInputs\s*=/);
+```
+
+You should call `document.querySelectorAll()` with `#snacks input[type=number]`.
+
+```js
+assert.match(calculateCalories.toString(), /document\.querySelectorAll\(('|")#snacks input\[type=number\]\1\)/);
+```
+
+You should assign the result of your `document.querySelectorAll()` call to `snacksNumberInputs`.
+
+```js
+assert.match(calculateCalories.toString(), /snacksNumberInputs\s*=\s*document\.querySelectorAll\(('|")#snacks input\[type=number\]\1\)/);
+```
+
+You should declare a `exerciseNumberInputs` variable.
+
+```js
+assert.match(calculateCalories.toString(), /exerciseNumberInputs\s*=/);
+```
+
+You should call `document.querySelectorAll()` with `#exercise input[type=number]`.
+
+```js
+assert.match(calculateCalories.toString(), /document\.querySelectorAll\(('|")#exercise input\[type=number\]\1\)/);
+```
+
+You should assign the result of your `document.querySelectorAll()` call to `exerciseNumberInputs`.
+
+```js
+assert.match(calculateCalories.toString(), /exerciseNumberInputs\s*=\s*document\.querySelectorAll\(('|")#exercise input\[type=number\]\1\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c11a0a090311dff55564.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c11a0a090311dff55564.md
new file mode 100644
index 00000000000..dd2be81cbc5
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c11a0a090311dff55564.md
@@ -0,0 +1,242 @@
+---
+id: 63c9c11a0a090311dff55564
+title: Step 70
+challengeType: 0
+dashedName: step-70
+---
+
+# --description--
+
+Now that you have your lists of elements, you can pass them to your `getCaloriesFromInputs` function to extract the calorie total.
+
+Declare a `breakfastCalories` variable, and assign it the result of calling `getCaloriesFromInputs` with `breakfastNumberInputs` as the argument.
+
+# --hints--
+
+Your `calculateCalories` function should have a `breakfastCalories` variable.
+
+```js
+assert.match(calculateCalories.toString(), /breakfastCalories\s*=/);
+```
+
+You should call `getCaloriesFromInputs` with `breakfastNumberInputs` as the argument.
+
+```js
+assert.match(calculateCalories.toString(), /getCaloriesFromInputs\s*\(\s*breakfastNumberInputs\s*\)/);
+```
+
+You should assign the result of `getCaloriesFromInputs` to `breakfastCalories`.
+
+```js
+assert.match(calculateCalories.toString(), /breakfastCalories\s*=\s*getCaloriesFromInputs\s*\(\s*breakfastNumberInputs\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c16dd75dd212dc12363c.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c16dd75dd212dc12363c.md
new file mode 100644
index 00000000000..779bb1a2aed
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c16dd75dd212dc12363c.md
@@ -0,0 +1,241 @@
+---
+id: 63c9c16dd75dd212dc12363c
+title: Step 71
+challengeType: 0
+dashedName: step-71
+---
+
+# --description--
+
+Now declare a `lunchCalories` variable, and give it the value of calling `getCaloriesFromInputs` with your `lunchNumberInputs`.
+
+# --hints--
+
+Your `calculateCalories` function should have a `lunchCalories` variable.
+
+```js
+assert.match(calculateCalories.toString(), /lunchCalories\s*=/);
+```
+
+You should call `getCaloriesFromInputs` with `lunchNumberInputs` as the argument.
+
+```js
+assert.match(calculateCalories.toString(), /getCaloriesFromInputs\s*\(\s*lunchNumberInputs\s*\)/);
+```
+
+You should assign the result of `getCaloriesFromInputs` to `lunchCalories`.
+
+```js
+assert.match(calculateCalories.toString(), /lunchCalories\s*=\s*getCaloriesFromInputs\s*\(\s*lunchNumberInputs\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c1ef134f3513e751c975.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c1ef134f3513e751c975.md
new file mode 100644
index 00000000000..4bd18bc353f
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9c1ef134f3513e751c975.md
@@ -0,0 +1,278 @@
+---
+id: 63c9c1ef134f3513e751c975
+title: Step 72
+challengeType: 0
+dashedName: step-72
+---
+
+# --description--
+
+Following this same pattern, declare variables for the `number` inputs in the `#dinner`, `#snacks`, and `#exercise` elements. Assign them the appropriate `getCaloriesFromInputs` calls.
+
+# --hints--
+
+Your `calculateCalories` function should have a `dinnerCalories` variable.
+
+```js
+assert.match(calculateCalories.toString(), /dinnerCalories\s*=/);
+```
+
+You should call `getCaloriesFromInputs` with `dinnerNumberInputs` as the argument.
+
+```js
+assert.match(calculateCalories.toString(), /getCaloriesFromInputs\s*\(\s*dinnerNumberInputs\s*\)/);
+```
+
+You should assign the result of `getCaloriesFromInputs` to `dinnerCalories`.
+
+```js
+assert.match(calculateCalories.toString(), /dinnerCalories\s*=\s*getCaloriesFromInputs\s*\(\s*dinnerNumberInputs\s*\)/);
+```
+
+Your `calculateCalories` function should have a `snacksCalories` variable.
+
+```js
+assert.match(calculateCalories.toString(), /snacksCalories\s*=/);
+```
+
+You should call `getCaloriesFromInputs` with `snacksNumberInputs` as the argument.
+
+```js
+assert.match(calculateCalories.toString(), /getCaloriesFromInputs\s*\(\s*snacksNumberInputs\s*\)/);
+```
+
+You should assign the result of `getCaloriesFromInputs` to `snacksCalories`.
+
+```js
+assert.match(calculateCalories.toString(), /snacksCalories\s*=\s*getCaloriesFromInputs\s*\(\s*snacksNumberInputs\s*\)/);
+```
+
+Your `calculateCalories` function should have a `exerciseCalories` variable.
+
+```js
+assert.match(calculateCalories.toString(), /exerciseCalories\s*=/);
+```
+
+You should call `getCaloriesFromInputs` with `exerciseNumberInputs` as the argument.
+
+```js
+assert.match(calculateCalories.toString(), /getCaloriesFromInputs\s*\(\s*exerciseNumberInputs\s*\)/);
+```
+
+You should assign the result of `getCaloriesFromInputs` to `exerciseCalories`.
+
+```js
+assert.match(calculateCalories.toString(), /exerciseCalories\s*=\s*getCaloriesFromInputs\s*\(\s*exerciseNumberInputs\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e3a83bb3e61a80eea564.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e3a83bb3e61a80eea564.md
new file mode 100644
index 00000000000..3df7e192a70
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e3a83bb3e61a80eea564.md
@@ -0,0 +1,249 @@
+---
+id: 63c9e3a83bb3e61a80eea564
+title: Step 73
+challengeType: 0
+dashedName: step-73
+---
+
+# --description--
+
+You also need to get the value of your `#budget` input. You already queried this at the top of your code, and set it to the `budgetNumberInput` variable. However, you used `getElementById`, which returns an `Element`, not a `NodeList`.
+
+A `NodeList` is an array-like, which means you can iterate through it and it shares some common methods with an array. For your `getCaloriesFromInputs` function, an array will work for the argument just as well as a `NodeList` does.
+
+Declare a `budgetCalories` variable and set it to the result of calling `getCaloriesFromInputs` – pass an array containing your `budgetNumberInput` as the argument.
+
+# --hints--
+
+Your `calculateCalories` function should have a `budgetCalories` variable.
+
+```js
+assert.match(calculateCalories.toString(), /budgetCalories\s*=/);
+```
+
+You should call `getCaloriesFromInputs` with `[budgetNumberInput]` as the argument.
+
+```js
+assert.match(calculateCalories.toString(), /getCaloriesFromInputs\s*\(\s*\[\s*budgetNumberInput\s*\]\s*\)/);
+```
+
+You should assign the result of `getCaloriesFromInputs` to `budgetCalories`.
+
+```js
+assert.match(calculateCalories.toString(), /budgetCalories\s*=\s*getCaloriesFromInputs\s*\(\s*\[\s*budgetNumberInput\s*\]\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e45519caf31b987fbb5f.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e45519caf31b987fbb5f.md
new file mode 100644
index 00000000000..c49004bbebb
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e45519caf31b987fbb5f.md
@@ -0,0 +1,247 @@
+---
+id: 63c9e45519caf31b987fbb5f
+title: Step 74
+challengeType: 0
+dashedName: step-74
+---
+
+# --description--
+
+Your `getCaloriesFromInputs` function will set the global error flag to `true` if an invalid input is detected. Add an `if` statement to your `calculateCalories` function that checks the truthiness of your global error flag, and if it is truthy then use `return` to end the function execution.
+
+# --hints--
+
+Your `calculateCalories` function should have an `if` statement.
+
+```js
+assert.match(calculateCalories.toString(), /if\s*\(/);
+```
+
+Your `if` statement should check the truthiness of the `isError` variable.
+
+```js
+assert.match(calculateCalories.toString(), /if\s*\(\s*isError\s*\)/);
+```
+
+Your `if` statement should use `return` to end the function execution.
+
+```js
+assert.match(calculateCalories.toString(), /if\s*\(\s*isError\s*\)\s*\{?\s*return;?\s*\}?\s*/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e4d2ff41811dd640504f.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e4d2ff41811dd640504f.md
new file mode 100644
index 00000000000..4f917ca49a0
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e4d2ff41811dd640504f.md
@@ -0,0 +1,257 @@
+---
+id: 63c9e4d2ff41811dd640504f
+title: Step 75
+challengeType: 0
+dashedName: step-75
+---
+
+# --description--
+
+It is time to start preparing your calculations. Start by declaring a `consumedCalories` variable, and assign it the sum of `breakfastCalories`, `lunchCalories`, `dinnerCalories`, and `snacksCalories` (note that order matters for the tests). Be sure to do this after your `if` statement.
+
+# --hints--
+
+Your function should have a `consumedCalories` variable.
+
+```js
+assert.match(calculateCalories.toString(), /consumedCalories\s*=/);
+```
+
+Your `consumedCalories` variable should come after your `if` statement.
+
+```js
+assert.isAbove(calculateCalories.toString().indexOf('consumedCalories'), calculateCalories.toString().indexOf('if'));
+```
+
+You should calculate the sum of `breakfastCalories`, `lunchCalories`, `dinnerCalories`, and `snacksCalories`, in order.
+
+```js
+assert.match(calculateCalories.toString(), /breakfastCalories\s*\+\s*lunchCalories\s*\+\s*dinnerCalories\s*\+\s*snacksCalories/);
+```
+
+You should assign the sum of `breakfastCalories`, `lunchCalories`, `dinnerCalories`, and `snacksCalories` to `consumedCalories`.
+
+```js
+assert.match(calculateCalories.toString(), /consumedCalories\s*=\s*breakfastCalories\s*\+\s*lunchCalories\s*\+\s*dinnerCalories\s*\+\s*snacksCalories/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e51b3a007a1eba1cd0f6.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e51b3a007a1eba1cd0f6.md
new file mode 100644
index 00000000000..81b19870fd2
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e51b3a007a1eba1cd0f6.md
@@ -0,0 +1,252 @@
+---
+id: 63c9e51b3a007a1eba1cd0f6
+title: Step 76
+challengeType: 0
+dashedName: step-76
+---
+
+# --description--
+
+Now declare a `remainingCalories` variable, and give it the value of subtracting `consumedCalories` from `budgetCalories` and adding `exerciseCalories`.
+
+# --hints--
+
+Your `calculateCalories` function should have a `remainingCalories` variable.
+
+```js
+assert.match(calculateCalories.toString(), /remainingCalories\s*=/);
+```
+
+You should find the value of `budgetCalories - consumedCalories + exerciseCalories`.
+
+```js
+assert.match(calculateCalories.toString(), /budgetCalories\s*-\s*consumedCalories\s*\+\s*exerciseCalories/);
+```
+
+You should assign the value of `budgetCalories - consumedCalories + exerciseCalories` to `remainingCalories`.
+
+```js
+assert.match(calculateCalories.toString(), /remainingCalories\s*=\s*budgetCalories\s*-\s*consumedCalories\s*\+\s*exerciseCalories/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e55b4b06c11fff555c64.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e55b4b06c11fff555c64.md
new file mode 100644
index 00000000000..bc911d3b831
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e55b4b06c11fff555c64.md
@@ -0,0 +1,267 @@
+---
+id: 63c9e55b4b06c11fff555c64
+title: Step 77
+challengeType: 0
+dashedName: step-77
+---
+
+# --description--
+
+You need to know if the user's calories are a surplus or a deficit. Declare a `surplusOrDeficit` variable.
+
+Use a ternary operator to set `surplusOrDeficit` to the string `Surplus` or `Deficit` depending on whether `remainingCalories` is greater than or equal to `0`. If it is greater than or equal to `0`, then `surplusOrDeficit` should be `Surplus`. Otherwise, it should be `Deficit`.
+
+# --hints--
+
+Your `calculateCalories` function should have a `surplusOrDeficit` variable.
+
+```js
+assert.match(calculateCalories.toString(), /surplusOrDeficit\s*=/g);
+```
+
+You should have a ternary operator that checks if `remainingCalories` is greater than or equal to `0`.
+
+```js
+assert.match(calculateCalories.toString(), /remainingCalories\s*>=\s*0\s*\?/g);
+```
+
+Your ternary operator return the string `Surplus` if `remainingCalories` is greater than or equal to `0`.
+
+```js
+assert.match(calculateCalories.toString(), /remainingCalories\s*>=\s*0\s*\?\s*('|")Surplus\1\s*:/g);
+```
+
+Your ternary operator return the string `Deficit` if `remainingCalories` is not greater than or equal to `0`.
+
+```js
+assert.match(calculateCalories.toString(), /remainingCalories\s*>=\s*0\s*\?\s*('|")Surplus\1\s*:\s*('|")Deficit\2/g);
+```
+
+You should assign the result of your ternary operator to `surplusOrDeficit`.
+
+```js
+assert.match(calculateCalories.toString(), /surplusOrDeficit\s*=\s*remainingCalories\s*>=\s*0\s*\?\s*('|")Surplus\1\s*:\s*('|")Deficit\2/g);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e5eea8261d22856ead1c.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e5eea8261d22856ead1c.md
new file mode 100644
index 00000000000..01ebba201d2
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e5eea8261d22856ead1c.md
@@ -0,0 +1,250 @@
+---
+id: 63c9e5eea8261d22856ead1c
+title: Step 78
+challengeType: 0
+dashedName: step-78
+---
+
+# --description--
+
+You need to construct the HTML string that will be displayed in the `output` element. Start by assigning an empty template literal to the `innerHTML` property of the `output` element.
+
+# --hints--
+
+You should access the `innerHTML` property of the `output` element.
+
+```js
+assert.match(calculateCalories.toString(), /output\s*\.\s*innerHTML/);
+```
+
+You should assign an empty template literal to the `innerHTML` property of the `output` element.
+
+```js
+// again, template literals don't play well with the parser so we have to look at the raw code.
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/;?\s*\}/)[0];
+assert.equal(htmlString, '``');
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e63bb1e32d23b6adbe44.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e63bb1e32d23b6adbe44.md
new file mode 100644
index 00000000000..5711b833a42
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e63bb1e32d23b6adbe44.md
@@ -0,0 +1,266 @@
+---
+id: 63c9e63bb1e32d23b6adbe44
+title: Step 79
+challengeType: 0
+dashedName: step-79
+---
+
+# --description--
+
+Your `output.innerHTML` string will need a `span` element. Create that, and give it a `class` attribute set to the `surplusOrDeficit` variable, but lowercased.
+
+Strings have a `.toLowerCase()` method that can help you with this. Do not give your `span` any text yet.
+
+# --hints--
+
+You should create a `span` element in your template literal.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.match(htmlString, //);
+```
+
+Your `span` should not have any text.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.match(htmlString, /<\/span>/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = ``;
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e6b7c0303524af2d0bc2.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e6b7c0303524af2d0bc2.md
new file mode 100644
index 00000000000..ee4568c97d6
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e6b7c0303524af2d0bc2.md
@@ -0,0 +1,245 @@
+---
+id: 63c9e6b7c0303524af2d0bc2
+title: Step 80
+challengeType: 0
+dashedName: step-80
+---
+
+# --description--
+
+Give your span the text `remainingCalories Calorie surplusOrDeficit`, using interpolation to replace `remainingCalories` and `surplusOrDeficit` with the appropriate variables.
+
+# --hints--
+
+Your `span` should have the text `${remainingCalories} Calorie ${surplusOrDeficit}`.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.match(htmlString, /\$\{remainingCalories\} Calorie \$\{surplusOrDeficit\}<\/span>/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+
+ `;
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e769df38c92635c158ba.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e769df38c92635c158ba.md
new file mode 100644
index 00000000000..cec54f93795
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e769df38c92635c158ba.md
@@ -0,0 +1,254 @@
+---
+id: 63c9e769df38c92635c158ba
+title: Step 81
+challengeType: 0
+dashedName: step-81
+---
+
+# --description--
+
+When the user has a calorie deficit, the `remainingCalories` value will be negative. You don't want to display a negative number in the result string.
+
+`Math.abs()` is a built-in JavaScript method that will return the absolute value of a number. In your `span` text, wrap your `remainingCalories` reference in `Math.abs()` to ensure that the value is positive.
+
+# --hints--
+
+You should wrap the `remainingCalories` variable in `Math.abs()`.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.match(htmlString, /Math\.abs\(\s*remainingCalories\s*\)/);
+```
+
+Your `span` should have the text `${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}`.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.match(htmlString, /\$\{Math\.abs\(remainingCalories\)\} Calorie \$\{surplusOrDeficit\}<\/span>/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${remainingCalories} Calorie ${surplusOrDeficit}
+ `;
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e7d5b21eee2776ecc226.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e7d5b21eee2776ecc226.md
new file mode 100644
index 00000000000..17ce6851e9c
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e7d5b21eee2776ecc226.md
@@ -0,0 +1,262 @@
+---
+id: 63c9e7d5b21eee2776ecc226
+title: Step 82
+challengeType: 0
+dashedName: step-82
+---
+
+# --description--
+
+After your `span` element, add an `hr` element to create a horizontal line.
+
+To keep your code clean and readable, you should add this on a new line in the template literal.
+
+# --hints--
+
+You should add an `hr` element to your `output.innerHTML` string.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.match(htmlString, / /);
+```
+
+Your `hr` element should come after your `span` element.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.isAbove(htmlString.indexOf(' /);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ `;
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e84c9fe8ca28c4101189.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e84c9fe8ca28c4101189.md
new file mode 100644
index 00000000000..ba1da012290
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e84c9fe8ca28c4101189.md
@@ -0,0 +1,270 @@
+---
+id: 63c9e84c9fe8ca28c4101189
+title: Step 83
+challengeType: 0
+dashedName: step-83
+---
+
+# --description--
+
+Now create a `p` element with the text `budgetCalories Calories Budgeted`, using interpolation to replace `budgetCalories` with the appropriate variable.
+
+This should come after your `hr` element.
+
+# --hints--
+
+You should create a `p` element.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.match(htmlString, //);
+```
+
+Your `p` element should come after your `hr` element.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.isAbove(htmlString.indexOf('
\$\{budgetCalories\}\s*Calories\s*Budgeted<\/p>/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+
+ `;
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e8fe3a6f022a05a04675.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e8fe3a6f022a05a04675.md
new file mode 100644
index 00000000000..6b28d6282ad
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e8fe3a6f022a05a04675.md
@@ -0,0 +1,269 @@
+---
+id: 63c9e8fe3a6f022a05a04675
+title: Step 84
+challengeType: 0
+dashedName: step-84
+---
+
+# --description--
+
+Using the same interpolation syntax, add a second `p` element with the text `consumedCalories Calories Consumed` and a third with the text `exerciseCalories Calories Burned`. Remember to replace your `consumedCalories` and `exerciseCalories` variables with the appropriate values.
+
+# --hints--
+
+You should add a second `p` element to your template literal.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.isAtLeast(htmlString.match(//g).length, 2);
+```
+
+Your second `p` element should be on a new line.
+
+```js
+const htmlString = code.split(/output\s*\.\s*innerHTML\s*=\s*/)[1].split(/`/)[1];
+assert.match(htmlString, /\n\s*
\$\{budgetCalories\}\s*Calories\s*Budgeted<\/p>\n\s*
\$\{consumedCalories\}\s*Calories\s*Consumed<\/p>/));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+
+ `;
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e94e9df7d72aed1c24bd.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e94e9df7d72aed1c24bd.md
new file mode 100644
index 00000000000..826bca08801
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9e94e9df7d72aed1c24bd.md
@@ -0,0 +1,264 @@
+---
+id: 63c9e94e9df7d72aed1c24bd
+title: Step 85
+challengeType: 0
+dashedName: step-85
+---
+
+# --description--
+
+Finally, you need to make the `#output` element visible so the user can see your text. Your `output` variable is an Element, which has a `classList` property. This property has a `.remove()` method, which accepts a string representing the class to remove from the element.
+
+Use the `.remove()` method of the `output` variable's `classList` property to remove the `hide` class. Don't forget to place the word `hide` inside quotes.
+
+# --hints--
+
+You should access the `classList` property of the `output` element.
+
+```js
+assert.match(calculateCalories.toString(), /output\.classList/);
+```
+
+You should call the `.remove()` method of the `classList` property.
+
+```js
+assert.match(calculateCalories.toString(), /output\.classList\.remove\(/);
+```
+
+You should pass `hide` as the argument to the `.remove()` method.
+
+```js
+assert.match(calculateCalories.toString(), /output\.classList\.remove\(\s*('|")hide\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+--fcc-editable-region--
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+
+}
+--fcc-editable-region--
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ea23dbadbf2c2764e3f5.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ea23dbadbf2c2764e3f5.md
new file mode 100644
index 00000000000..18e5f04d27a
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ea23dbadbf2c2764e3f5.md
@@ -0,0 +1,265 @@
+---
+id: 63c9ea23dbadbf2c2764e3f5
+title: Step 86
+challengeType: 0
+dashedName: step-86
+---
+
+# --description--
+
+If you click on your `Calculate Remaining Calories` button, you'll see that nothing happens. You still need to mount the event listener.
+
+Add an event listener to your `calorieCounter` element. The event type should be `submit`, and the callback function should be `calculateCalories`.
+
+# --hints--
+
+You should use the `.addEventListener()` method of your `calorieCounter` element.
+
+```js
+assert.match(code, /calorieCounter\.addEventListener\(/);
+```
+
+You should pass `submit` as the first argument to `.addEventListener()`.
+
+```js
+assert.match(code, /calorieCounter\.addEventListener\(\s*('|")submit\1\s*/);
+```
+
+You should pass `calculateCalories` as the second argument to `.addEventListener()`.
+
+```js
+assert.match(code, /calorieCounter\.addEventListener\(\s*('|")submit\1\s*,\s*calculateCalories\s*/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+ output.classList.remove('hide');
+}
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+addEntryButton.addEventListener("click", addEntry);
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ea9b16430f2d54522464.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ea9b16430f2d54522464.md
new file mode 100644
index 00000000000..6c09fd6f149
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ea9b16430f2d54522464.md
@@ -0,0 +1,265 @@
+---
+id: 63c9ea9b16430f2d54522464
+title: Step 87
+challengeType: 0
+dashedName: step-87
+---
+
+# --description--
+
+Your final feature to add is the ability for a user to clear the form. Start by declaring an empty function called `clearForm` – it should not take any arguments.
+
+# --hints--
+
+You should declare a `clearForm` variable.
+
+```js
+assert.isDefined(clearForm);
+```
+
+Your `clearForm` variable should be a function.
+
+```js
+assert.isFunction(clearForm);
+```
+
+Your `clearForm` function should not take any arguments.
+
+```js
+assert.match(clearForm?.toString(), /\(\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+ output.classList.remove('hide');
+}
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+--fcc-editable-region--
+
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+calorieCounter.addEventListener("submit", calculateCalories);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9eb09bcfaa72e3da820a1.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9eb09bcfaa72e3da820a1.md
new file mode 100644
index 00000000000..7810095dcce
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9eb09bcfaa72e3da820a1.md
@@ -0,0 +1,267 @@
+---
+id: 63c9eb09bcfaa72e3da820a1
+title: Step 88
+challengeType: 0
+dashedName: step-88
+---
+
+# --description--
+
+You need to get all of the input containers. Declare an `inputContainers` variable, and assign it to the value of querying the document for all elements with the class `input-container`.
+
+# --hints--
+
+You should declare an `inputContainers` variable in your `clearForm` function.
+
+```js
+assert.match(clearForm.toString(), /inputContainers\s*=/);
+```
+
+You should use the `querySelectorAll` method to get all of the elements with the class `input-container`.
+
+```js
+assert.match(clearForm.toString(), /document\.querySelectorAll\(\s*('|")\.input-container\1\s*\)/);
+```
+
+You should assign the value of the `querySelectorAll` method to the `inputContainers` variable.
+
+```js
+assert.match(clearForm.toString(), /inputContainers\s*=\s*document\.querySelectorAll\(\s*('|")\.input-container\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+ output.classList.remove('hide');
+}
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+--fcc-editable-region--
+function clearForm() {
+
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+calorieCounter.addEventListener("submit", calculateCalories);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9eb4a5d68f12f32d9b440.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9eb4a5d68f12f32d9b440.md
new file mode 100644
index 00000000000..73d20bba696
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9eb4a5d68f12f32d9b440.md
@@ -0,0 +1,263 @@
+---
+id: 63c9eb4a5d68f12f32d9b440
+title: Step 89
+challengeType: 0
+dashedName: step-89
+---
+
+# --description--
+
+Remember that `document.querySelectorAll` returns a `NodeList`, which is array-like but is not an array. However, the `Array` object has a `.from()` method that accepts an array-like and returns an array. This is helpful when you want access to more robust array methods, which you will learn about in a future project.
+
+Wrap your `inputContainers` query selector in `Array.from()`. Do this on the same line as your declaration.
+
+# --hints--
+
+You should wrap your `querySelectorAll` in `Array.from()`.
+
+```js
+assert.match(clearForm, /Array\.from\(\s*document\.querySelectorAll\(\s*('|")\.input-container*\1\s*\)\s*\)/);
+```
+
+You should assign the result of `Array.from()` to your `inputContainers` variable.
+
+```js
+assert.match(clearForm, /inputContainers\s*=\s*Array\.from\(\s*document\.querySelectorAll\(\s*('|")\.input-container*\1\s*\)\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+ output.classList.remove('hide');
+}
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+--fcc-editable-region--
+function clearForm() {
+ const inputContainers = document.querySelectorAll('.input-container');
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+calorieCounter.addEventListener("submit", calculateCalories);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ebb7b12bca3025b0a935.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ebb7b12bca3025b0a935.md
new file mode 100644
index 00000000000..f6655dc9175
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ebb7b12bca3025b0a935.md
@@ -0,0 +1,276 @@
+---
+id: 63c9ebb7b12bca3025b0a935
+title: Step 90
+challengeType: 0
+dashedName: step-90
+---
+
+# --description--
+
+It is time for another loop. Use a `for` loop to iterate through the `inputContainers` array.
+
+Inside the loop, set the `innerHTML` property of the element at the current index to an empty string. This will clear all of the contents of that input container.
+
+# --hints--
+
+Your `clearForm` function should have a `for` loop.
+
+```js
+// loop protect injects stuff, so let's look at the raw code again
+const clearForm = code.split("function clearForm()")[1];
+assert.match(clearForm, /for\s*\(/);
+```
+
+Your `for` loop should iterate through the `inputContainers` array. Remember to use `i` as your iterator.
+
+```js
+const clearForm = code.split("function clearForm()")[1];
+assert.match(clearForm, /for\s*\(\s*let\s+i\s*=\s*0\s*;\s*i\s*<\s*inputContainers\.length\s*;\s*i\s*\+\+\s*\)/);
+```
+
+Your `for` loop should set the `innerHTML` property of `inputContainers[i]` to an empty string.
+
+```js
+const clearForm = code.split("function clearForm()")[1];
+const forLoop = clearForm.split("for")[1];
+assert.match(forLoop, /inputContainers\[\s*i\s*\]\s*\.innerHTML\s*=\s*(`|'|")\1\s*/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+ output.classList.remove('hide');
+}
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+--fcc-editable-region--
+function clearForm() {
+ const inputContainers = Array.from(document.querySelectorAll('.input-container'));
+
+
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+calorieCounter.addEventListener("submit", calculateCalories);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ec044acedf312c4974ff.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ec044acedf312c4974ff.md
new file mode 100644
index 00000000000..5ef4abce954
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9ec044acedf312c4974ff.md
@@ -0,0 +1,275 @@
+---
+id: 63c9ec044acedf312c4974ff
+title: Step 91
+challengeType: 0
+dashedName: step-91
+---
+
+# --description--
+
+After your loop completes, you need to clear the `budgetNumberInput`. Set the `value` property of `budgetNumberInput` to an empty string.
+
+# --hints--
+
+Your `clearForm` function should access the `value` property of the `budgetNumberInput` element.
+
+```js
+assert.match(clearForm.toString(), /budgetNumberInput\.value/);
+```
+
+Your `clearForm` function should set the `value` property of the `budgetNumberInput` element to an empty string.
+
+```js
+assert.match(clearForm.toString(), /budgetNumberInput\.value\s*=\s*('|"|`)\1/);
+```
+
+You should modify the `budgetNumberInput` after your `for` loop.
+
+```js
+const clearForm = code.split("function clearForm()")[1];
+const afterLoop = clearForm.split("}")[1];
+assert.match(afterLoop, /budgetNumberInput\.value/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+ output.classList.remove('hide');
+}
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+--fcc-editable-region--
+function clearForm() {
+ const inputContainers = Array.from(document.querySelectorAll('.input-container'));
+
+ for (let i = 0; i < inputContainers.length; i++) {
+ inputContainers[i].innerHTML = '';
+ }
+
+
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+calorieCounter.addEventListener("submit", calculateCalories);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9f24afbc9cf324dcaa9a4.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9f24afbc9cf324dcaa9a4.md
new file mode 100644
index 00000000000..3dab9bed7e5
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9f24afbc9cf324dcaa9a4.md
@@ -0,0 +1,276 @@
+---
+id: 63c9f24afbc9cf324dcaa9a4
+title: Step 92
+challengeType: 0
+dashedName: step-92
+---
+
+# --description--
+
+You also need to clear the `output` element's text. You can do this by setting the `innerText` property to an empty string.
+
+The difference between `innerText` and `innerHTML` is that `innerText` will not render HTML elements, but will display the tags and content as raw text.
+
+# --hints--
+
+Your `clearForm` function should access the `innerText` property of the `output` element.
+
+```js
+assert.match(clearForm.toString(), /output\.innerText/);
+```
+
+Your `clearForm` function should set the `innerText` property of the `output` element to an empty string.
+
+```js
+assert.match(clearForm.toString(), /output\.innerText\s*=\s*('|"|`)\1/);
+```
+
+You should modify `output` after modifying `budgetNumberInput`.
+
+```js
+assert.isAbove(clearForm.toString().indexOf('output'), clearForm.toString().indexOf('budgetNumberInput'));
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+ output.classList.remove('hide');
+}
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+--fcc-editable-region--
+function clearForm() {
+ const inputContainers = Array.from(document.querySelectorAll('.input-container'));
+
+ for (let i = 0; i < inputContainers.length; i++) {
+ inputContainers[i].innerHTML = '';
+ }
+
+ budgetNumberInput.value = '';
+
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+calorieCounter.addEventListener("submit", calculateCalories);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9f28bda3e3f336e21b6b4.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9f28bda3e3f336e21b6b4.md
new file mode 100644
index 00000000000..b2e9d536a15
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9f28bda3e3f336e21b6b4.md
@@ -0,0 +1,277 @@
+---
+id: 63c9f28bda3e3f336e21b6b4
+title: Step 93
+challengeType: 0
+dashedName: step-93
+---
+
+# --description--
+
+To finish off this function, you need to restore the `hide` class to the `output` element. The `classList` property has an `.add()` method which is the opposite of the `.remove()` method. It accepts a string representing the class to add to the element.
+
+Add the `hide` class to your `output`.
+
+# --hints--
+
+You should access the `classList` property of the `output` element.
+
+```js
+assert.match(clearForm.toString(), /output\.classList/);
+```
+
+You should call the `.add()` method on the `classList` property of the `output` element.
+
+```js
+assert.match(clearForm.toString(), /output\.classList\.add/);
+```
+
+You should pass `hide` as the argument to the `.add()` method.
+
+```js
+assert.match(clearForm.toString(), /output\.classList\.add\(\s*('|")hide\1\s*\)/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+ output.classList.remove('hide');
+}
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+--fcc-editable-region--
+function clearForm() {
+ const inputContainers = Array.from(document.querySelectorAll('.input-container'));
+
+ for (let i = 0; i < inputContainers.length; i++) {
+ inputContainers[i].innerHTML = '';
+ }
+
+ budgetNumberInput.value = '';
+ output.innerText = '';
+
+}
+--fcc-editable-region--
+
+addEntryButton.addEventListener("click", addEntry);
+calorieCounter.addEventListener("submit", calculateCalories);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9f2bff625af342023512c.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9f2bff625af342023512c.md
new file mode 100644
index 00000000000..d29b3f2ac72
--- /dev/null
+++ b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/63c9f2bff625af342023512c.md
@@ -0,0 +1,520 @@
+---
+id: 63c9f2bff625af342023512c
+title: Step 94
+challengeType: 0
+dashedName: step-94
+---
+
+# --description--
+
+To complete this project, add an event listener to the `clearButton` button. When the button is clicked, it should call the `clearForm` function.
+
+Congratulations! Your project is complete.
+
+# --hints--
+
+You should add an event listener to the `clearButton` button.
+
+```js
+assert.match(code, /clearButton\s*\.addEventListener\s*\(/);
+```
+
+You should pass `click` as the first argument to `.addEventListener()`.
+
+```js
+assert.match(code, /clearButton\s*\.addEventListener\s*\(\s*('|"|`)click\1\s*/);
+```
+
+You should pass `clearForm` as the second argument to `.addEventListener()`.
+
+```js
+assert.match(code, /clearButton\s*\.addEventListener\s*\(\s*('|"|`)click\1\s*,\s*clearForm\s*/);
+```
+
+# --seed--
+
+## --seed-contents--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+ output.classList.remove('hide');
+}
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+function clearForm() {
+ const inputContainers = Array.from(document.querySelectorAll('.input-container'));
+
+ for (let i = 0; i < inputContainers.length; i++) {
+ inputContainers[i].innerHTML = '';
+ }
+
+ budgetNumberInput.value = '';
+ output.innerText = '';
+ output.classList.add('hide');
+}
+
+addEntryButton.addEventListener("click", addEntry);
+calorieCounter.addEventListener("submit", calculateCalories);
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
+
+# --solutions--
+
+```html
+
+
+
+
+
+
+ Calorie Counter
+
+
+
+ Calorie Counter
+
+
+
+
+
+```
+
+```css
+body {
+ font-family: "Lato", Arial;
+}
+
+h1 {
+ text-align: center;
+}
+
+.container {
+ width: 90%;
+ max-width: 680px;
+}
+
+h1,
+.container,
+.output {
+ margin: 20px auto;
+}
+
+label,
+legend {
+ font-weight: bold;
+}
+
+.input-container {
+ display: flex;
+ flex-direction: column;
+}
+
+button:hover {
+ cursor: pointer;
+}
+
+fieldset,
+label,
+button,
+input,
+select {
+ margin-bottom: 10px;
+}
+
+.output {
+ border: 2px solid black;
+ padding: 10px;
+ text-align: center;
+}
+
+.hide {
+ display: none;
+}
+
+.output span {
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+.surplus {
+ color: #006627;
+}
+
+.deficit {
+ color: #B30000;
+}
+```
+
+```js
+const calorieCounter = document.getElementById('calorie-counter');
+const budgetNumberInput = document.getElementById('budget');
+const entryDropdown = document.getElementById('entry-dropdown');
+const addEntryButton = document.getElementById('add-entry');
+const clearButton = document.getElementById('clear');
+const output = document.getElementById('output');
+let isError = false;
+
+function cleanInputString(str) {
+ const regex = /[+-\s]/g;
+ return str.replace(regex, '');
+}
+
+function isInvalidInput(str) {
+ const regex = /\d+e\d+/i;
+ return str.match(regex);
+}
+
+function addEntry() {
+ const targetInputContainer = document.querySelector(`#${entryDropdown.value} .input-container`);
+ const entryNumber = targetInputContainer.querySelectorAll('input[type="text"]').length + 1;
+ const HTMLString = `
+ Entry ${entryNumber} Name
+
+ Entry ${entryNumber} Calories
+ `;
+ targetInputContainer.insertAdjacentHTML('beforeend', HTMLString);
+}
+
+function calculateCalories(e) {
+ e.preventDefault();
+ isError = false;
+
+ const breakfastNumberInputs = document.querySelectorAll('#breakfast input[type=number]');
+ const lunchNumberInputs = document.querySelectorAll('#lunch input[type=number]');
+ const dinnerNumberInputs = document.querySelectorAll('#dinner input[type=number]');
+ const snacksNumberInputs = document.querySelectorAll('#snacks input[type=number]');
+ const exerciseNumberInputs = document.querySelectorAll('#exercise input[type=number]');
+
+ const breakfastCalories = getCaloriesFromInputs(breakfastNumberInputs);
+ const lunchCalories = getCaloriesFromInputs(lunchNumberInputs);
+ const dinnerCalories = getCaloriesFromInputs(dinnerNumberInputs);
+ const snacksCalories = getCaloriesFromInputs(snacksNumberInputs);
+ const exerciseCalories = getCaloriesFromInputs(exerciseNumberInputs);
+ const budgetCalories = getCaloriesFromInputs([budgetNumberInput]);
+
+ if (isError) {
+ return;
+ }
+
+ const consumedCalories = breakfastCalories + lunchCalories + dinnerCalories + snacksCalories;
+ const remainingCalories = budgetCalories - consumedCalories + exerciseCalories;
+ const surplusOrDeficit = remainingCalories >= 0 ? 'Surplus' : 'Deficit';
+ output.innerHTML = `
+ ${Math.abs(remainingCalories)} Calorie ${surplusOrDeficit}
+
+ ${budgetCalories} Calories Budgeted
+ ${consumedCalories} Calories Consumed
+ ${exerciseCalories} Calories Burned
+ `;
+
+ output.classList.remove('hide');
+}
+
+function getCaloriesFromInputs(list) {
+ let calories = 0;
+
+ for (let i = 0; i < list.length; i++) {
+ const currVal = cleanInputString(list[i].value);
+ const invalidInputMatch = isInvalidInput(currVal);
+
+ if (invalidInputMatch) {
+ alert(`Invalid Input: ${invalidInputMatch[0]}`);
+ isError = true;
+ return null;
+ }
+ calories += Number(currVal);
+ }
+ return calories;
+}
+
+function clearForm() {
+ const inputContainers = Array.from(document.querySelectorAll('.input-container'));
+
+ for (let i = 0; i < inputContainers.length; i++) {
+ inputContainers[i].innerHTML = '';
+ }
+
+ budgetNumberInput.value = '';
+ output.innerText = '';
+ output.classList.add('hide');
+}
+
+addEntryButton.addEventListener('click', addEntry);
+calorieCounter.addEventListener('submit', calculateCalories);
+clearButton.addEventListener('click', clearForm);
+```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/step-001.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/step-001.md
deleted file mode 100644
index a2ce162457c..00000000000
--- a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/step-001.md
+++ /dev/null
@@ -1,100 +0,0 @@
----
-id: 5ddb965c65d27e1512d44d9a
-title: Step 1
-challengeType: 0
-dashedName: step-1
----
-
-# --description--
-
-When a browser loads a page, it creates a Document Object Model (DOM) representation of the page which includes all of the HTML elements in a tree structure.
-
-In JavaScript, you can access the DOM by referencing the global `document` object.
-
-To view the DOM, log it to the console with `console.log(document)`.
-
-# --hints--
-
-See description above for instructions.
-
-```js
-assert(code.replace(/\s/g, '').match(/console\.log\(document\)/));
-```
-
-# --seed--
-
-## --before-user-code--
-
-```html
-
-
-
-
-
-
-
-
-
-
-
-```
-
-## --after-user-code--
-
-```html
-
-
-```
-
-## --seed-contents--
-
-```html
-
-```
-
-# --solutions--
-
-```html
-
-```
diff --git a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/step-002.md b/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/step-002.md
deleted file mode 100644
index aab244748d6..00000000000
--- a/curriculum/challenges/english/15-javascript-algorithms-and-data-structures-22/learn-form-validation-by-building-a-calorie-counter/step-002.md
+++ /dev/null
@@ -1,114 +0,0 @@
----
-id: 5ddb965c65d27e1512d44d9b
-title: Step 2
-challengeType: 0
-dashedName: step-2
----
-
-# --description--
-
-In our HTML document, we have a form element with an `id` attribute: `